diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java
index 9ed5e5e0b..b49372693 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java
@@ -81,6 +81,8 @@ public class NativeJDBCSeq
private String _tableName = "DUAL";
private boolean _subTable = false;
+ private String _schema = null;
+
/**
* The sequence name. Defaults to OPENJPA_SEQUENCE
.
*/
@@ -169,9 +171,12 @@ public class NativeJDBCSeq
if (group.isKnownSequence(_seqName))
return;
- String schemaName = Strings.getPackageName(_seqName);
- if (schemaName.length() == 0)
- schemaName = Schemas.getNewTableSchema(_conf);
+ String schemaName = getSchema();
+ if (schemaName == null || schemaName.length() == 0) {
+ schemaName = Strings.getPackageName(_seqName);
+ if (schemaName.length() == 0)
+ schemaName = Schemas.getNewTableSchema(_conf);
+ }
// create table in this group
Schema schema = group.getSchema(schemaName);
@@ -228,9 +233,17 @@ public class NativeJDBCSeq
*/
private void buildSequence() {
String seqName = Strings.getClassName(_seqName);
- String schemaName = Strings.getPackageName(_seqName);
- if (schemaName.length() == 0)
- schemaName = Schemas.getNewTableSchema(_conf);
+ // JPA 2 added schema as a configurable attribute on
+ // sequence generator. OpenJPA <= 1.x allowed this via
+ // schema.sequence on the sequence name. Specifying a schema
+ // name on the annotation or in the orm will override the old
+ // behavior.
+ String schemaName = _schema;
+ if (schemaName == null || schemaName.length() == 0) {
+ schemaName = Strings.getPackageName(_seqName);
+ if (schemaName.length() == 0)
+ schemaName = Schemas.getNewTableSchema(_conf);
+ }
// build the sequence in one of the designated schemas
SchemaGroup group = new SchemaGroup();
@@ -380,4 +393,12 @@ public class NativeJDBCSeq
return false;
return true;
}
+
+ public void setSchema(String _schema) {
+ this._schema = _schema;
+ }
+
+ public String getSchema() {
+ return _schema;
+ }
}
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/SequenceMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/SequenceMetaData.java
index 1daf9cc78..a917cd6a3 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/SequenceMetaData.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/SequenceMetaData.java
@@ -67,6 +67,8 @@ public class SequenceMetaData
private static final String PROP_INITIAL_VALUE = "InitialValue";
private static final String PROP_ALLOCATE = "Allocate";
private static final String PROP_INCREMENT = "Increment";
+ private static final String PROP_SCHEMA = "Schema";
+ private static final String PROP_CATALOG = "Catalog";
private static final Localizer _loc = Localizer.forPackage
(SequenceMetaData.class);
@@ -87,6 +89,8 @@ public class SequenceMetaData
private int _increment = -1;
private int _allocate = -1;
private int _initial = -1;
+ private String _schema = null;
+ private String _catalog = null;
// instantiated lazily
private transient Seq _instance = null;
@@ -306,6 +310,28 @@ public class SequenceMetaData
}
}
+ /*
+ * Set/Get the schema name
+ */
+ public void setSchema(String schema) {
+ this._schema = schema;
+ }
+
+ public String getSchema() {
+ return _schema;
+ }
+
+ /*
+ * Set/Get the catalog name
+ */
+ public void setCatalog(String catalog) {
+ this._catalog = catalog;
+ }
+
+ public String getCatalog() {
+ return _catalog;
+ }
+
/**
* Create a new plugin value for sequences. Returns a standard
* {@link SeqValue} by default.
@@ -322,6 +348,8 @@ public class SequenceMetaData
appendProperty(props, PROP_INITIAL_VALUE, _initial);
appendProperty(props, PROP_ALLOCATE, _allocate);
appendProperty(props, PROP_INCREMENT, _increment);
+ appendProperty(props, PROP_SCHEMA, _schema);
+ appendProperty(props, PROP_CATALOG, _catalog);
}
/**
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/NativeORMSequenceEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/NativeORMSequenceEntity.java
new file mode 100644
index 000000000..520e977e6
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/NativeORMSequenceEntity.java
@@ -0,0 +1,46 @@
+/*
+ * 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.jdbc.annotations;
+
+// This entity is defined via sequence-orm.xml
+public class NativeORMSequenceEntity {
+
+ public static final String SCHEMA_NAME = "ORMSCHEMA";
+ public static final String SEQ_NAME = "ORMSEQ";
+
+ private int id;
+
+ private String name;
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/NativeSequenceEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/NativeSequenceEntity.java
new file mode 100644
index 000000000..87a259468
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/NativeSequenceEntity.java
@@ -0,0 +1,61 @@
+/*
+ * 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.jdbc.annotations;
+
+import javax.persistence.Basic;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Table;
+
+import static javax.persistence.GenerationType.SEQUENCE;
+import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
+
+@Entity
+@Table(name="NativeSeqEnt")
+public class NativeSequenceEntity {
+
+ public static final String SEQ_NAME = "SCHEMASEQ";
+ public static final String SCHEMA_NAME = "SEQSCHEMA";
+
+ @Id
+ @SequenceGenerator(name="seq_with_schema", sequenceName=SEQ_NAME,
+ schema=SCHEMA_NAME, initialValue=10)
+ @GeneratedValue(strategy=SEQUENCE, generator="seq_with_schema")
+ private int id;
+
+ @Basic
+ private String name;
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestSequenceGenerator.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestSequenceGenerator.java
new file mode 100644
index 000000000..a3080aa76
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestSequenceGenerator.java
@@ -0,0 +1,120 @@
+/*
+ * 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.jdbc.annotations;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.schema.Sequence;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
+import org.apache.openjpa.persistence.test.AllowFailure;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Test for sequence generator. Some databases currently (Derby) do not support
+ * native sequences so this method is allowed to fail until such time when the
+ * test corpus can support database or dictionary support specific
+ * configuration.
+ *
+ * @author Jeremy Bauer
+ */
+@AllowFailure(true)
+public class TestSequenceGenerator extends SingleEMFTestCase {
+
+ public void setUp()
+ throws Exception {
+ setUp(NativeSequenceEntity.class,
+ NativeORMSequenceEntity.class,
+ CLEAR_TABLES);
+ }
+
+ @Override
+ protected String getPersistenceUnitName() {
+ return "native-seq-pu";
+ }
+
+ /*
+ * Test use of the schema attribute on a native sequence generator. Some
+ * databases do not support native sequences so this method is
+ * currently allowed to fail.
+ */
+ public void testSequenceSchema() {
+ OpenJPAEntityManagerSPI em = emf.createEntityManager();
+ NativeSequenceEntity nse = new NativeSequenceEntity();
+ nse.setName("Test");
+ em.getTransaction().begin();
+ em.persist(nse);
+ em.getTransaction().commit();
+ em.refresh(nse);
+ // Validate the id is >= the initial value
+ // Assert the sequence was created in the DB
+ assertTrue(sequenceExists(em, NativeSequenceEntity.SCHEMA_NAME,
+ NativeSequenceEntity.SEQ_NAME));
+ // Assert the id is >= the initial value
+ assertTrue(nse.getId() >= 10);
+ em.close();
+ }
+
+ /*
+ * Test use of the schema element on a native sequence generator. Some
+ * databases do not support native sequences so this method is
+ * currently allowed to fail.
+ */
+ public void testORMSequenceSchema() {
+ OpenJPAEntityManagerSPI em = emf.createEntityManager();
+ NativeORMSequenceEntity nse = new NativeORMSequenceEntity();
+ nse.setName("TestORM");
+ em.getTransaction().begin();
+ em.persist(nse);
+ em.getTransaction().commit();
+ em.refresh(nse);
+ // Assert the sequence was created in the DB
+ assertTrue(sequenceExists(em, NativeORMSequenceEntity.SCHEMA_NAME,
+ NativeORMSequenceEntity.SEQ_NAME));
+ // Assert the id is >= the initial value
+ assertTrue(nse.getId() >= 2000);
+ em.close();
+ }
+
+ /**
+ * Method to verify a sequence was created for the given schema and
+ * sequence name.
+ */
+ private boolean sequenceExists(OpenJPAEntityManagerSPI em, String schema,
+ String sequence) {
+ JDBCConfiguration conf = (JDBCConfiguration) emf.getConfiguration();
+ DBDictionary dict = conf.getDBDictionaryInstance();
+ Connection conn = (Connection)em.getConnection();
+ try {
+ DatabaseMetaData dbmd = conn.getMetaData();
+ Sequence[] seqs = dict.getSequences(dbmd, null, schema,
+ sequence, conn);
+ if (seqs != null && seqs.length == 1 &&
+ seqs[0].getName().equalsIgnoreCase(sequence) &&
+ seqs[0].getSchemaName().equalsIgnoreCase(schema))
+ return true;
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml b/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml
index 8f7373753..d11531faa 100644
--- a/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml
+++ b/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml
@@ -113,4 +113,14 @@
+
+ org/apache/openjpa/persistence/sequence/sequence-orm.xml
+ org.apache.openjpa.persistence.jdbc.annotations.NativeSequenceEntity
+ org.apache.openjpa.persistence.jdbc.annotations.NativeORMSequenceEntity
+
+
+
+
+
diff --git a/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/sequence/sequence-orm.xml b/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/sequence/sequence-orm.xml
new file mode 100644
index 000000000..d11d681a0
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/sequence/sequence-orm.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
index 20b754c13..02adf96ac 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
@@ -1570,6 +1570,8 @@ public class AnnotationPersistenceMetaDataParser
String seq = gen.sequenceName();
int initial = gen.initialValue();
int allocate = gen.allocationSize();
+ String schema = gen.schema();
+ String catalog = gen.catalog();
// don't allow initial of 0 b/c looks like def value
if (initial == 0)
initial = 1;
@@ -1593,6 +1595,8 @@ public class AnnotationPersistenceMetaDataParser
meta.setSequence(seq);
meta.setInitialValue(initial);
meta.setAllocate(allocate);
+ meta.setSchema(schema);
+ meta.setCatalog(catalog);
meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
meta.SRC_ANNOTATIONS);
}
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataSerializer.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataSerializer.java
index b07336c64..66d1330ad 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataSerializer.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataSerializer.java
@@ -696,6 +696,10 @@ public class AnnotationPersistenceMetaDataSerializer
ab.add("initialValue", meta.getInitialValue());
if (meta.getAllocate() != 50 && meta.getAllocate() != -1)
ab.add("allocationSize", meta.getAllocate());
+ if (meta.getSchema() != null)
+ ab.add("schema", meta.getSchema());
+ if (meta.getCatalog() != null)
+ ab.add("catalog", meta.getCatalog());
}
/**
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
index a8179f9d3..785d05e5b 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
@@ -958,6 +958,8 @@ public class XMLPersistenceMetaDataParser
int initial = val == null ? 1 : Integer.parseInt(val);
val = attrs.getValue("allocation-size");
int allocate = val == null ? 50 : Integer.parseInt(val);
+ String schema = attrs.getValue("schema");
+ String catalog = attrs.getValue("catalog");
String clsName, props;
if (seq == null || seq.indexOf('(') == -1) {
@@ -973,6 +975,8 @@ public class XMLPersistenceMetaDataParser
meta.setSequence(seq);
meta.setInitialValue(initial);
meta.setAllocate(allocate);
+ meta.setSchema(schema);
+ meta.setCatalog(catalog);
Object cur = currentElement();
Object scope = (cur instanceof ClassMetaData)