From 151cf2d034e904110ac1d19747319034943753de Mon Sep 17 00:00:00 2001 From: Michael Dick Date: Fri, 12 Oct 2007 23:42:34 +0000 Subject: [PATCH] OPENJPA-399 committing Teresa's patch git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@584330 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/jdbc/kernel/TableJDBCSeq.java | 84 +++++-- .../apache/openjpa/jdbc/schema/Column.java | 8 + .../openjpa/jdbc/schema/LocalConstraint.java | 5 - .../openjpa/jdbc/schema/SchemaGroup.java | 69 ++++- .../openjpa/jdbc/schema/SchemaTool.java | 12 +- .../org/apache/openjpa/jdbc/schema/Table.java | 2 +- .../persistence/generationtype/Dog1.java | 96 +++++++ .../persistence/generationtype/Dog2.java | 96 +++++++ .../persistence/generationtype/DogId.java | 103 ++++++++ .../persistence/generationtype/DogTable.java | 101 ++++++++ .../persistence/generationtype/DogTable2.java | 100 ++++++++ .../TestMultipleSchemaNames.java | 237 ++++++++++++++++++ .../src/doc/manual/jpa_overview_meta.xml | 13 + .../src/doc/manual/ref_guide_dbsetup.xml | 13 + .../src/doc/manual/ref_guide_runtime.xml | 5 +- 15 files changed, 909 insertions(+), 35 deletions(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogId.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java index 1974aeea2..52897c274 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java @@ -24,11 +24,13 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; +import java.util.HashMap; import org.apache.openjpa.jdbc.conf.JDBCConfiguration; import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl; import org.apache.openjpa.jdbc.meta.ClassMapping; import org.apache.openjpa.jdbc.schema.Column; +import org.apache.openjpa.jdbc.schema.Index; import org.apache.openjpa.jdbc.schema.PrimaryKey; import org.apache.openjpa.jdbc.schema.Schema; import org.apache.openjpa.jdbc.schema.SchemaGroup; @@ -77,7 +79,7 @@ public class TableJDBCSeq private transient Log _log = null; private int _alloc = 50; private int _intValue = 1; - private final Status _stat = new Status(); + private final HashMap _stat = new HashMap(); private String _table = "OPENJPA_SEQUENCE_TABLE"; private String _seqColumnName = "SEQUENCE_VALUE"; @@ -85,6 +87,7 @@ public class TableJDBCSeq private Column _seqColumn = null; private Column _pkColumn = null; + private int _schemasIdx = 0; /** * The sequence table name. Defaults to OPENJPA_SEQUENCE_TABLE. @@ -212,20 +215,37 @@ public class TableJDBCSeq buildTable(); } + public void addSchema(ClassMapping mapping, SchemaGroup group) { - // table already exists? - if (group.isKnownTable(_table)) - return; + // Since the table is created by openjpa internally + // we can create the table for each schema within the PU + // in here. + + Schema[] schemas = group.getSchemas(); + for (int i = 0; i < schemas.length; i++) { + String schemaName = Strings.getPackageName(_table); + if (schemaName.length() == 0) + schemaName = Schemas.getNewTableSchema(_conf); + if (schemaName == null) + schemaName = schemas[i].getName(); - String schemaName = Strings.getPackageName(_table); - if (schemaName.length() == 0) - schemaName = Schemas.getNewTableSchema(_conf); - - // create table in this group - Schema schema = group.getSchema(schemaName); - if (schema == null) - schema = group.addSchema(schemaName); - schema.importTable(_pkColumn.getTable()); + // create table in this group + Schema schema = group.getSchema(schemaName); + if (schema == null) + schema = group.addSchema(schemaName); + + schema.importTable(_pkColumn.getTable()); + // build the index for the sequence tables + // the index name will the fully qualified table name +_IDX + Table tab = schema.getTable(_table); + Index idx = tab.addIndex(tab.getFullName()+"_IDX"); + idx.setUnique(true); + // we need to reset the table name in the column with the + // fully qualified name for matching the table name from the + // Column. + _pkColumn.resetTableName(schemaName+"."+_pkColumn.getTableName()); + idx.addColumn(_pkColumn); + } } protected Object nextInternal(JDBCStore store, ClassMapping mapping) @@ -285,8 +305,14 @@ public class TableJDBCSeq * Return the appropriate status object for the given class, or null * if cannot handle the given class. The mapping may be null. */ - protected Status getStatus(ClassMapping mapping) { - return _stat; + protected Status getStatus(ClassMapping mapping) { + Status status = (Status)_stat.get(mapping); + if (status == null){ + status = new Status(); + _stat.put(mapping, status); + } + return status; + } /** @@ -392,8 +418,9 @@ public class TableJDBCSeq getClass(), mapping)); DBDictionary dict = _conf.getDBDictionaryInstance(); + String tableName = resolveTableName(mapping, _pkColumn.getTable()); SQLBuffer insert = new SQLBuffer(dict).append("INSERT INTO "). - append(_pkColumn.getTable()).append(" ("). + append(tableName).append(" ("). append(_pkColumn).append(", ").append(_seqColumn). append(") VALUES ("). appendValue(pk, _pkColumn).append(", "). @@ -431,7 +458,8 @@ public class TableJDBCSeq SQLBuffer sel = new SQLBuffer(dict).append(_seqColumn); SQLBuffer where = new SQLBuffer(dict).append(_pkColumn).append(" = "). appendValue(pk, _pkColumn); - SQLBuffer tables = new SQLBuffer(dict).append(_seqColumn.getTable()); + String tableName = resolveTableName(mapping, _seqColumn.getTable()); + SQLBuffer tables = new SQLBuffer(dict).append(tableName); SQLBuffer select = dict.toSelect(sel, null, tables, where, null, null, null, false, dict.supportsSelectForUpdate, 0, Long.MAX_VALUE); @@ -467,7 +495,7 @@ public class TableJDBCSeq throw new InvalidStateException(_loc.get("bad-seq-type", getClass(), mapping)); - DBDictionary dict = _conf.getDBDictionaryInstance(); + DBDictionary dict = _conf.getDBDictionaryInstance(); SQLBuffer where = new SQLBuffer(dict).append(_pkColumn).append(" = "). appendValue(pk, _pkColumn); @@ -486,7 +514,8 @@ public class TableJDBCSeq // update the value upd = new SQLBuffer(dict); - upd.append("UPDATE ").append(_seqColumn.getTable()). + String tableName = resolveTableName(mapping, _seqColumn.getTable()); + upd.append("UPDATE ").append(tableName). append(" SET ").append(_seqColumn).append(" = "). appendValue(Numbers.valueOf(cur + inc), _seqColumn). append(" WHERE ").append(where).append(" AND "). @@ -503,7 +532,7 @@ public class TableJDBCSeq } } - // setup new sequence range + // setup new sequence range synchronized (stat) { if (updateStatSeq && stat.seq < cur) stat.seq = cur; @@ -512,6 +541,21 @@ public class TableJDBCSeq } return true; } + /** + * Resolve a fully qualified table name + * + * @param class + * mapping to get the schema name + */ + public String resolveTableName(ClassMapping mapping, Table table) { + String sName = mapping.getTable().getSchemaName(); + String tableName; + if (sName == null) + tableName = table.getFullName(); + else + tableName = sName + "." + table.getFullName(); + return tableName; + } /** * Creates the sequence table in the DB. diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java index 77f0133ba..deda088e8 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Column.java @@ -180,6 +180,14 @@ public class Column _tableName = name; _fullName = null; } + + /** + * Reset the table name with the fully qualified table name which + * includes the schema name + */ + public void resetTableName(String name) { + _tableName = name; + } /** * The column's schema name. diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/LocalConstraint.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/LocalConstraint.java index 683b8c6cf..c68a674b7 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/LocalConstraint.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/LocalConstraint.java @@ -93,11 +93,6 @@ public abstract class LocalConstraint * Add a column to the constraint. */ public void addColumn(Column col) { - if (col == null || !ObjectUtils.equals(col.getTable(), getTable())) - throw new InvalidStateException(_loc.get("table-mismatch", - col == null ? null : col.getTable(), - col == null ? null : getTable())); - if (_colList == null) _colList = new ArrayList(3); else if (_colList.contains(col)) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGroup.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGroup.java index e9e478e46..a5d7fd3f3 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGroup.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGroup.java @@ -186,6 +186,42 @@ public class SchemaGroup return null; } + /** + * Find the table with the given name in the group, using '.' as the catalog + * separator. Returns null if no table found. + */ + public Table findTable(Schema inSchema, String name) { + if (name == null) + return null; + + int dotIdx = name.indexOf('.'); + if (dotIdx != -1) { + String schemaName = name.substring(0, dotIdx); + name = name.substring(dotIdx + 1); + Schema schema = getSchema(schemaName); + if (schema != null) + return schema.getTable(name); + } else { + Schema[] schemas = getSchemas(); + for (int i = 0; i < schemas.length; i++) { + Table tab = schemas[i].getTable(name); + // if a table is found and it has the same schema + // as the input schema , it means that the table + // exists. However, if the input schema is null, + // then we assume that there is only one table for the + // db default schema, in this case, table exists.. + // We can't handle the case that one entity has schema name + // and other entity does not have schema name but both entities + // map to the same table. + if (tab != null + && (schemas[i] == inSchema || inSchema.getName() == null)) + return tab; + + } + } + return null; + } + /** * Return true if the given sequence is known to exist. While * {@link #findSequence} may exhibit dynamic behavior in some schema group @@ -242,8 +278,37 @@ public class SchemaGroup } /** - * Find all foreign keys exported by a given primary key (all foreign - * keys that link to the primary key). + * Find the sequence with the given name in the group, using '.' as the + * catalog separator. Returns null if no sequence found. + */ + public Sequence findSequence(Schema inSchema, String name) { + if (name == null) + return null; + + int dotIdx = name.indexOf('.'); + if (dotIdx != -1) { + String schemaName = name.substring(0, dotIdx); + name = name.substring(dotIdx + 1); + Schema schema = getSchema(schemaName); + if (schema != null) + return schema.getSequence(name); + } else { + Schema[] schemas = getSchemas(); + Sequence seq; + for (int i = 0; i < schemas.length; i++) { + seq = schemas[i].getSequence(name); + if ((seq != null) + && (schemas[i] == inSchema || inSchema.getName() == null)) + return seq; + } + + } + return null; + } + + /** + * Find all foreign keys exported by a given primary key (all foreign keys + * that link to the primary key). */ public ForeignKey[] findExportedForeignKeys(PrimaryKey pk) { if (pk == null) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java index 131186fae..199b624d4 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java @@ -450,7 +450,7 @@ public class SchemaTool { for (int i = 0; i < schemas.length; i++) { seqs = schemas[i].getSequences(); for (int j = 0; j < seqs.length; j++) { - if (db.findSequence(seqs[j]) != null) + if (db.findSequence(schemas[i], seqs[j].getFullName()) != null) continue; if (createSequence(seqs[j])) { @@ -473,7 +473,7 @@ public class SchemaTool { tabs = schemas[i].getTables(); for (int j = 0; j < tabs.length; j++) { cols = tabs[j].getColumns(); - dbTable = db.findTable(tabs[j]); + dbTable = db.findTable(schemas[i], tabs[j].getFullName()); for (int k = 0; k < cols.length; k++) { if (dbTable != null) { col = dbTable.getColumn(cols[k].getName()); @@ -500,7 +500,7 @@ public class SchemaTool { tabs = schemas[i].getTables(); for (int j = 0; j < tabs.length; j++) { pk = tabs[j].getPrimaryKey(); - dbTable = db.findTable(tabs[j]); + dbTable = db.findTable(schemas[i], tabs[j].getFullName()); if (pk != null && !pk.isLogical() && dbTable != null) { if (dbTable.getPrimaryKey() == null && addPrimaryKey(pk)) @@ -520,7 +520,7 @@ public class SchemaTool { for (int i = 0; i < schemas.length; i++) { tabs = schemas[i].getTables(); for (int j = 0; j < tabs.length; j++) { - if (db.findTable(tabs[j]) != null) + if (db.findTable(schemas[i], tabs[j].getFullName()) != null) continue; if (createTable(tabs[j])) { @@ -546,7 +546,7 @@ public class SchemaTool { continue; idxs = tabs[j].getIndexes(); - dbTable = db.findTable(tabs[j]); + dbTable = db.findTable(schemas[i], tabs[j].getFullName()); for (int k = 0; k < idxs.length; k++) { if (dbTable != null) { idx = findIndex(dbTable, idxs[k]); @@ -596,7 +596,7 @@ public class SchemaTool { continue; fks = tabs[j].getForeignKeys(); - dbTable = db.findTable(tabs[j]); + dbTable = db.findTable(schemas[i],tabs[j].getFullName()); for (int k = 0; k < fks.length; k++) { if (!fks[k].isLogical() && dbTable != null) { fk = findForeignKey(dbTable, fks[k]); diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java index ebf1f4066..926cccf14 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java @@ -498,7 +498,7 @@ public class Table * Return the table's indexes. */ public Index[] getIndexes() { - if (_idxs == null) + if (_idxs == null || _idxs.length == 0) _idxs = (_idxMap == null) ? Schemas.EMPTY_INDEXES : (Index[]) _idxMap.values().toArray(new Index[_idxMap.size()]); return _idxs; diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java new file mode 100644 index 000000000..b6ee13c95 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.generationtype; + +import javax.persistence.*; +import java.io.*; + +/** + * Extension of Animal class illustrating inheritance. + */ +@Entity(name = "Dog1") +@Table(name = "DOGTAB", schema = "SCHEMA1") +@IdClass(DogId.class) +public class Dog1 implements Serializable + +{ + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id2; + + @Id + private int datastoreid; + + private String name; + + private float price; + + private boolean domestic; + + public Dog1() { + super(); + + } + + public Dog1(String name) { + this.id2 = id2; + this.name = name; + + } + + public int getId2() { + return id2; + } + + public void setId2(int id) { + this.id2 = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + this.price = price; + } + + public boolean isDomestic() { + return domestic; + } + + public void setDomestic(boolean domestic) { + this.domestic = domestic; + } + + public int getDatastoreid() { + return datastoreid; + } + + public void setDatastoreid(int datastoreid) { + this.datastoreid = datastoreid; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java new file mode 100644 index 000000000..9e7c5656a --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.generationtype; + +import javax.persistence.*; +import java.io.*; + +/** + * Extension of Animal class illustrating inheritance. + */ +@Entity(name = "Dog2") +@Table(name = "DOGTAB", schema = "SCHEMA2") +@IdClass(DogId.class) +public class Dog2 implements Serializable + +{ + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id2; + + @Id + private int datastoreid; + + private String name; + + private float price; + + private boolean domestic; + + public Dog2() { + super(); + + } + + public Dog2(String name) { + this.id2 = id2; + this.name = name; + + } + + public int getId2() { + return id2; + } + + public void setId2(int id) { + this.id2 = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + this.price = price; + } + + public boolean isDomestic() { + return domestic; + } + + public void setDomestic(boolean domestic) { + this.domestic = domestic; + } + + public int getDatastoreid() { + return datastoreid; + } + + public void setDatastoreid(int datastoreid) { + this.datastoreid = datastoreid; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogId.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogId.java new file mode 100644 index 000000000..f7d68629d --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogId.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.generationtype; + + +import java.io.*; + +/** + * Application identity class for: tutorial.ejb.Animal + * + * Auto-generated by: org.apache.openjpa.enhance.ApplicationIdTool + */ +public class DogId implements Serializable { + static { + // register persistent class in JVM + try { + Class.forName("tutorial.ejb.Dog"); + } catch (Exception e) { + } + } + + public int id2; + + public int datastoreid; + + public DogId() { + } + + public DogId(String str) { + fromString(str); + } + + public String toString() { + return String.valueOf(id2) + "::" + datastoreid; + } + + public int hashCode() { + int rs = 17; + rs = rs * 37 + (int) (id2 ^ (id2 >>> 32)); + rs = rs + * 37 + + ((datastoreid == 0) ? 0 : new Integer(datastoreid).hashCode()); + return rs; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || obj.getClass() != getClass()) + return false; + + DogId other = (DogId) obj; + return (id2 == other.id2) + && ((datastoreid == 0 && other.datastoreid == 0) || (datastoreid != 0 && datastoreid == other.datastoreid)); + } + + private void fromString(String str) { + Tokenizer toke = new Tokenizer(str); + str = toke.nextToken(); + id2 = Integer.parseInt(str); + str = toke.nextToken(); + datastoreid = Integer.parseInt(str); + } + + protected static class Tokenizer { + private final String str; + + private int last; + + public Tokenizer(String str) { + this.str = str; + } + + public String nextToken() { + int next = str.indexOf("::", last); + String part; + if (next == -1) { + part = str.substring(last); + last = str.length(); + } else { + part = str.substring(last, next); + last = next + 2; + } + return part; + } + } +} \ No newline at end of file diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java new file mode 100644 index 000000000..537ccec76 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.generationtype; + + +import javax.persistence.*; +import java.io.*; + +/** + * Extension of Animal class illustrating inheritance. + */ +@Entity(name = "DogTable") +@Table(name = "DOGTABLE", schema = "SCHEMA1") +@IdClass(DogId.class) +public class DogTable implements Serializable + +{ + @Id + @TableGenerator(name = "Dog_Gen1", table = "ID_Gen1", + pkColumnName = "GEN_NAME", valueColumnName = "GEN_VAL", + pkColumnValue = "ID2", initialValue = 20, allocationSize = 10) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "Dog_Gen1") + private int id2; + + @Id + private int datastoreid; + + private String name; + + private float price; + + private boolean domestic; + + public DogTable() { + super(); + + } + + public DogTable(String name) { + this.id2 = id2; + this.name = name; + + } + + public int getId2() { + return id2; + } + + public void setId2(int id) { + this.id2 = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + + this.price = price; + } + + public boolean isDomestic() { + return domestic; + } + + public void setDomestic(boolean domestic) { + this.domestic = domestic; + } + + public int getDatastoreid() { + return datastoreid; + } + + public void setDatastoreid(int datastoreid) { + this.datastoreid = datastoreid; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java new file mode 100644 index 000000000..4ddf69e5b --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.generationtype; + +import java.io.*; +import javax.persistence.*; + +/** + * Extension of Animal class illustrating inheritance. + */ +@Entity(name = "DogTable2") +@Table(name = "DOGTABLE", schema = "SCHEMA2") +@IdClass(DogId.class) +public class DogTable2 implements Serializable + +{ + @Id + @TableGenerator(name = "Dog_Gen2", table = "ID_Gen2", + pkColumnName = "GEN_NAME", valueColumnName = "GEN_VAL", + pkColumnValue = "ID2", initialValue = 100, allocationSize = 10) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "Dog_Gen2") + private int id2; + + @Id + private int datastoreid; + + private String name; + + private float price; + + private boolean domestic; + + public DogTable2() { + super(); + + } + + public DogTable2(String name) { + this.id2 = id2; + this.name = name; + + } + + public int getId2() { + return id2; + } + + public void setId2(int id) { + this.id2 = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + + this.price = price; + } + + public boolean isDomestic() { + return domestic; + } + + public void setDomestic(boolean domestic) { + this.domestic = domestic; + } + + public int getDatastoreid() { + return datastoreid; + } + + public void setDatastoreid(int datastoreid) { + this.datastoreid = datastoreid; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java new file mode 100644 index 000000000..c3a44c4ed --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java @@ -0,0 +1,237 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.generationtype; + +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.Query; +import org.apache.openjpa.persistence.*; +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +public class TestMultipleSchemaNames extends SingleEMFTestCase { + public void setUp() { + setUp(Dog1.class, Dog2.class, DogTable.class, DogTable2.class); + + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + // cleanup database first + Query qry = em.createQuery("select d from Dog1 d"); + List result = qry.getResultList(); + + for (int index = 0; index < result.size(); index++) { + Dog1 Obj = (Dog1) result.get(index); + em.remove(Obj); + } + Query qry2 = em.createQuery("select d from Dog2 d"); + List result2 = qry2.getResultList(); + + for (int index = 0; index < result2.size(); index++) { + Dog2 Obj = (Dog2) result2.get(index); + em.remove(Obj); + } + Query qry3 = em.createQuery("select d from DogTable d"); + List result3 = qry3.getResultList(); + + for (int index = 0; index < result3.size(); index++) { + DogTable Obj = (DogTable) result3.get(index); + em.remove(Obj); + } + Query qry4 = em.createQuery("select d from DogTable2 d"); + List result4 = qry4.getResultList(); + + for (int index = 0; index < result4.size(); index++) { + DogTable2 Obj = (DogTable2) result4.get(index); + em.remove(Obj); + } + + Query delschema1 = em + .createNativeQuery("delete from schema1.openjpa_sequence_table"); + delschema1.executeUpdate(); + Query delschema2 = em + .createNativeQuery("delete from schema2.openjpa_sequence_table"); + delschema2.executeUpdate(); + Query delgentable = em.createNativeQuery("delete from schema1.id_gen1"); + delgentable.executeUpdate(); + Query delgentable2 = em + .createNativeQuery("delete from schema2.id_gen2"); + delgentable2.executeUpdate(); + + em.getTransaction().commit(); + + } + + public void testGeneratedAUTO() { + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager kem = OpenJPAPersistence.cast(em); + em.getTransaction().begin(); + + Dog1 dog1 = new Dog1(); + dog1.setName("helloDog1"); + dog1.setDatastoreid(12); + dog1.setPrice(12000); + + em.persist(dog1); + Dog1 dog1a = new Dog1(); + dog1a.setName("helloDog2"); + dog1a.setDatastoreid(15); + dog1a.setPrice(22000); + em.persist(dog1a); + // add dog2 + Dog2 dog2 = new Dog2(); + dog2.setName("helloDog3"); + dog2.setDatastoreid(12); + dog2.setPrice(15000); + em.persist(dog2); + + Dog2 dog2a = new Dog2(); + dog2a.setName("helloDog4"); + dog2a.setDatastoreid(19); + dog2a.setPrice(25000); + em.persist(dog2a); + em.getTransaction().commit(); + // System.out.println("persist dogs are done"); + + Dog1 dog1x = em.find(Dog1.class, kem.getObjectId(dog1)); + assertTrue(dog1x.getId2() == 1 || dog1x.getId2() == 2); + assertEquals(dog1x.getName(), "helloDog1"); + dog1x.setName("Dog1"); + dog1x.setDomestic(true); + Dog1 dog11 = em.find(Dog1.class, kem.getObjectId(dog1a)); + assertTrue(dog11.getId2() == 1 || dog11.getId2() == 2); + assertEquals(dog11.getName(), "helloDog2"); + dog11.setName("Dog2"); + dog11.setDomestic(true); + // update dog2 + Dog2 dog2x = em.find(Dog2.class, kem.getObjectId(dog2)); + assertTrue(dog2x.getId2() == 1 || dog2x.getId2() == 2); + assertEquals(dog2x.getName(), "helloDog3"); + dog2x.setName("Dog3"); + dog2x.setDomestic(true); + Dog2 dog21 = em.find(Dog2.class, kem.getObjectId(dog2a)); + assertTrue(dog21.getId2() == 1 || dog21.getId2() == 2); + assertEquals(dog21.getName(), "helloDog4"); + dog21.setName("Dog4"); + dog21.setDomestic(true); + + // get the update dog name + + em.getTransaction().begin(); + Query qry1 = em.createQuery("select d from Dog1 d order by d.name"); + List result1 = qry1.getResultList(); + for (int index = 0; index < result1.size(); index++) { + Dog1 dog4 = (Dog1) result1.get(index); + int i = index + 1; + assertTrue(dog4.getId2() == 1 || dog4.getId2() == 2); + assertEquals(dog4.getName(), "Dog" + i); + } + + Query qry2 = em.createQuery("select d from Dog2 d order by d.name"); + List result2 = qry2.getResultList(); + + for (int index = 0; index < result2.size(); index++) { + Dog2 dog5 = (Dog2) result2.get(index); + assertTrue(dog5.getId2() == 1 || dog5.getId2() == 2); + int j = index + 3; + assertEquals(dog5.getName(), "Dog" + j); + } + + em.getTransaction().commit(); + em.close(); + } + + public void testGeneratedTABLE() { + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager kem = OpenJPAPersistence.cast(em); + em.getTransaction().begin(); + + DogTable dog1 = new DogTable(); + dog1.setName("helloDog1"); + dog1.setDatastoreid(12); + dog1.setPrice(12000); + + em.persist(dog1); + DogTable dog1a = new DogTable(); + dog1a.setName("helloDog2"); + dog1a.setDatastoreid(15); + dog1a.setPrice(22000); + em.persist(dog1a); + // add dog2 + DogTable2 dog2 = new DogTable2(); + dog2.setName("helloDog3"); + dog2.setDatastoreid(12); + dog2.setPrice(15000); + em.persist(dog2); + + DogTable2 dog2a = new DogTable2(); + dog2a.setName("helloDog4"); + dog2a.setDatastoreid(19); + dog2a.setPrice(25000); + em.persist(dog2a); + em.getTransaction().commit(); + + DogTable dog1x = em.find(DogTable.class, kem.getObjectId(dog1)); + assertTrue(dog1x.getId2() == 20 || dog1x.getId2() == 21); + assertEquals(dog1x.getName(), "helloDog1"); + dog1x.setName("Dog1"); + dog1x.setDomestic(true); + DogTable dog11 = em.find(DogTable.class, kem.getObjectId(dog1a)); + assertTrue(dog11.getId2() == 20 || dog11.getId2() == 21); + assertEquals(dog11.getName(), "helloDog2"); + dog11.setName("Dog2"); + dog11.setDomestic(true); + // update dog2 + DogTable2 dog2x = em.find(DogTable2.class, kem.getObjectId(dog2)); + assertTrue(dog2x.getId2() == 100 || dog2x.getId2() == 101); + assertEquals(dog2x.getName(), "helloDog3"); + dog2x.setName("Dog3"); + dog2x.setDomestic(true); + DogTable2 dog21 = em.find(DogTable2.class, kem.getObjectId(dog2a)); + assertTrue(dog2x.getId2() == 100 || dog2x.getId2() == 101); + assertEquals(dog21.getName(), "helloDog4"); + dog21.setName("Dog4"); + dog21.setDomestic(true); + + // get the update dog name + + em.getTransaction().begin(); + Query qry1 = em.createQuery("select d from DogTable d order by d.name"); + List result1 = qry1.getResultList(); + for (int index = 0; index < result1.size(); index++) { + DogTable dog4 = (DogTable) result1.get(index); + assertTrue(dog4.getId2() == 20 || dog4.getId2() == 21); + int j = index + 1; + assertEquals(dog4.getName(), "Dog" + j); + + } + + Query qry2 = em + .createQuery("select d from DogTable2 d order by d.name"); + List result2 = qry2.getResultList(); + + for (int index = 0; index < result2.size(); index++) { + DogTable2 dog5 = (DogTable2) result2.get(index); + assertTrue(dog5.getId2() == 100 || dog5.getId2() == 101); + int j = index + 3; + assertEquals(dog5.getName(), "Dog" + j); + } + + em.getTransaction().commit(); + em.close(); + } +} // end of TestMultipleSchemaNames diff --git a/openjpa-project/src/doc/manual/jpa_overview_meta.xml b/openjpa-project/src/doc/manual/jpa_overview_meta.xml index e4f7e7c97..5d90a6f89 100644 --- a/openjpa-project/src/doc/manual/jpa_overview_meta.xml +++ b/openjpa-project/src/doc/manual/jpa_overview_meta.xml @@ -883,6 +883,19 @@ These string constants are defined in org.apache.openjpa.persistence.Generator. + +If the entities are mapped to the same table name but with different schema +name within one PersistenceUnit intentionally, and the +strategy of GeneratedType.AUTO is used to generate the ID +for each entity, a schema name for each entity must be explicitly declared +either through the annotation or the mapping.xml file. Otherwise, the mapping +tool only creates the tables for those entities with the schema names under +each schema. In addition, there will be only one +OPENJPA_SEQUENCE_TABLE created for all the entities within +the PersistenceUnit if the entities are not identified +with the schema name. Read and + in the Reference Guide. +
diff --git a/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml b/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml index b83dbb4d2..a39294bf6 100644 --- a/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml +++ b/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml @@ -3299,6 +3299,19 @@ The Schema property also establishes the default schema for new tables created through OpenJPA tools, such as the mapping tool covered in . + +If the entities are mapped to the same table name but with different schema +name within one PersistenceUnit intentionally, and the +strategy of GeneratedType.AUTO is used to generate the ID +for each entity, a schema name for each entity must be explicitly declared +either through the annotation or the mapping.xml file. Otherwise, the mapping +tool only creates the tables for those entities with the schema names under +each schema. In addition, there will be only one +OPENJPA_SEQUENCE_TABLE created for all the entities within +the PersistenceUnit if the entities are not identified +with the schema name. +Read in the Reference Guide. +
diff --git a/openjpa-project/src/doc/manual/ref_guide_runtime.xml b/openjpa-project/src/doc/manual/ref_guide_runtime.xml index cea92f5dc..8b87c4a02 100644 --- a/openjpa-project/src/doc/manual/ref_guide_runtime.xml +++ b/openjpa-project/src/doc/manual/ref_guide_runtime.xml @@ -1455,7 +1455,10 @@ This <classname>Seq</classname> has the following properties: <listitem> <para> <literal>Table</literal>: The name of the sequence number table to use. -Defaults to <literal>OPENJPA_SEQUENCE_TABLE</literal>. +Defaults to <literal>OPENJPA_SEQUENCE_TABLE</literal>. If the entities are +mapped to the same table name but with different schema name within one +PersistenceUnit, one <literal>OPENJPA_SEQUENCE_TABLE</literal> is created +for each schema. </para> </listitem> <listitem>