mirror of https://github.com/apache/openjpa.git
OPENJPA-1235 Added support for named unique constraints
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@802864 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
538f1fd084
commit
9af553bc8d
|
@ -92,6 +92,7 @@ public class TableJDBCSeq
|
|||
private String _seqColumnName = "SEQUENCE_VALUE";
|
||||
private String _pkColumnName = "ID";
|
||||
private String[] _uniqueColumnNames;
|
||||
private String _uniqueConstraintName;
|
||||
|
||||
private Column _seqColumn = null;
|
||||
private Column _pkColumn = null;
|
||||
|
@ -397,7 +398,10 @@ public class TableJDBCSeq
|
|||
_seqColumn.setJavaType(JavaTypes.LONG);
|
||||
|
||||
if (_uniqueColumnNames != null) {
|
||||
String uniqueName = dict.getValidUniqueName("UNQ", table);
|
||||
String uniqueName = _uniqueConstraintName;
|
||||
if (StringUtils.isEmpty(uniqueName)) {
|
||||
uniqueName = dict.getValidUniqueName("UNQ", table);
|
||||
}
|
||||
Unique u = table.addUnique(uniqueName);
|
||||
for (String columnName : _uniqueColumnNames) {
|
||||
if (!table.containsColumn(columnName))
|
||||
|
@ -805,6 +809,14 @@ public class TableJDBCSeq
|
|||
return dict.getLong(rs, 1);
|
||||
}
|
||||
|
||||
public void setUniqueConstraintName(String _uniqueConstraintName) {
|
||||
this._uniqueConstraintName = _uniqueConstraintName;
|
||||
}
|
||||
|
||||
public String getUniqueConstraintName() {
|
||||
return _uniqueConstraintName;
|
||||
}
|
||||
|
||||
/**
|
||||
* AllocateSequenceRunnable is a runnable wrapper that will inserts the
|
||||
* initial sequence value into the database.
|
||||
|
|
|
@ -62,6 +62,7 @@ public class SequenceMapping
|
|||
private static final String PROP_PK_COL = "PrimaryKeyColumn";
|
||||
private static final String PROP_PK_VALUE = "PrimaryKeyValue";
|
||||
private static final String PROP_UNIQUE = "UniqueColumns";
|
||||
private static final String PROP_UNIQUE_CONSTRAINT = "UniqueConstraintName";
|
||||
|
||||
private File _mapFile = null;
|
||||
private String _table = null;
|
||||
|
@ -69,6 +70,7 @@ public class SequenceMapping
|
|||
private String _primaryKeyColumn = null;
|
||||
private String _primaryKeyValue = null;
|
||||
private String[] _uniqueColumns = null;
|
||||
private String _uniqueConstraintName = null;
|
||||
|
||||
public SequenceMapping(String name, MappingRepository repos) {
|
||||
super(name, repos);
|
||||
|
@ -175,6 +177,12 @@ public class SequenceMapping
|
|||
// Array of unique column names are passed to configuration
|
||||
// as a single string "x|y|z". The configurable (TableJDBCSeq) must
|
||||
// parse it back.
|
||||
if (_uniqueConstraintName != null &&
|
||||
_uniqueConstraintName.length() > 0) {
|
||||
appendProperty(props, PROP_UNIQUE_CONSTRAINT,
|
||||
addQuotes(_uniqueConstraintName));
|
||||
}
|
||||
|
||||
if (_uniqueColumns != null && _uniqueColumns.length > 0)
|
||||
appendProperty(props, PROP_UNIQUE,
|
||||
StringUtils.join(_uniqueColumns,'|'));
|
||||
|
@ -186,4 +194,14 @@ public class SequenceMapping
|
|||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setUniqueConstraintName(String name) {
|
||||
_uniqueConstraintName = name;
|
||||
|
||||
}
|
||||
|
||||
public String getUniqueConstraintName() {
|
||||
return _uniqueConstraintName;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -277,6 +277,7 @@ public class AnnotationPersistenceMappingParser
|
|||
break; // nothing to do
|
||||
case 1:
|
||||
meta.setUniqueColumns(gen.uniqueConstraints()[0].columnNames());
|
||||
meta.setUniqueConstraintName(gen.uniqueConstraints()[0].name());
|
||||
break;
|
||||
default:
|
||||
log.warn(_loc.get("unique-many-on-seq-unsupported", el, name));
|
||||
|
@ -558,6 +559,10 @@ public class AnnotationPersistenceMappingParser
|
|||
column.setName(columnNames[i]);
|
||||
uniqueConstraint.addColumn(column);
|
||||
}
|
||||
String name = anno.name();
|
||||
if (!StringUtils.isEmpty(name)) {
|
||||
uniqueConstraint.setName(name);
|
||||
}
|
||||
return uniqueConstraint;
|
||||
}
|
||||
|
||||
|
|
|
@ -601,6 +601,9 @@ public class AnnotationPersistenceMappingSerializer
|
|||
if (columns.length > 1)
|
||||
sb.insert(0, "{").append("}");
|
||||
ab.add("columnNames", sb.toString());
|
||||
if (StringUtils.isNotEmpty(unique.getName())) {
|
||||
ab.add("name", unique.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -96,6 +96,7 @@ enum MappingTag {
|
|||
MAP_KEY_TEMPORAL,
|
||||
MAPPING_OVERRIDE,
|
||||
MAPPING_OVERRIDES,
|
||||
NAME,
|
||||
NONPOLY,
|
||||
ORDER_COL,
|
||||
STRAT,
|
||||
|
|
|
@ -99,6 +99,7 @@ public class XMLPersistenceMappingParser
|
|||
_elems.put("map-key-column", MAP_KEY_COL);
|
||||
_elems.put("map-key-join-column", MAP_KEY_JOIN_COL);
|
||||
_elems.put("map-key-temporal", MAP_KEY_TEMPORAL);
|
||||
_elems.put("name", NAME);
|
||||
_elems.put("order-column", ORDER_COLUMN);
|
||||
_elems.put("primary-key-join-column", PK_JOIN_COL);
|
||||
_elems.put("secondary-table", SECONDARY_TABLE);
|
||||
|
@ -249,6 +250,9 @@ public class XMLPersistenceMappingParser
|
|||
case UNIQUE:
|
||||
ret = startUniqueConstraint(attrs);
|
||||
break;
|
||||
case NAME:
|
||||
ret = true;
|
||||
break;
|
||||
case TEMPORAL:
|
||||
case ENUMERATED:
|
||||
case MAP_KEY_ENUMERATED:
|
||||
|
@ -285,6 +289,19 @@ public class XMLPersistenceMappingParser
|
|||
return (ret) ? tag : null;
|
||||
}
|
||||
|
||||
private boolean endName() {
|
||||
String name = this.currentText();
|
||||
if (StringUtils.isNotEmpty(name)) {
|
||||
Object current = currentElement();
|
||||
if (current instanceof Unique) {
|
||||
Unique unq = (Unique)current;
|
||||
unq.setName(name);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void endClassMappingElement(String name)
|
||||
throws SAXException {
|
||||
|
@ -333,6 +350,9 @@ public class XMLPersistenceMappingParser
|
|||
case TABLE_GEN:
|
||||
endTableGenerator();
|
||||
break;
|
||||
case NAME:
|
||||
endName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1130,6 +1150,14 @@ public class XMLPersistenceMappingParser
|
|||
private boolean startUniqueConstraint(Attributes attrs)
|
||||
throws SAXException {
|
||||
Unique unique = new Unique();
|
||||
// TODO JRB: If the spec is corrected, get the unique constraint name
|
||||
// via attribute
|
||||
/*
|
||||
String name = attrs.getValue("name");
|
||||
if (StringUtils.isNotEmpty(name)) {
|
||||
unique.setName(name);
|
||||
}
|
||||
*/
|
||||
pushElement(unique);
|
||||
return true;
|
||||
}
|
||||
|
@ -1161,6 +1189,9 @@ public class XMLPersistenceMappingParser
|
|||
for (Column uniqueColumn : uniqueColumns)
|
||||
columnNames[i++] = uniqueColumn.getName();
|
||||
seq.setUniqueColumns(columnNames);
|
||||
if (StringUtils.isNotEmpty(unique.getName())) {
|
||||
seq.setUniqueConstraintName(unique.getName());
|
||||
}
|
||||
} else {
|
||||
throw new InternalException();
|
||||
}
|
||||
|
|
|
@ -566,6 +566,14 @@ public class XMLPersistenceMappingSerializer
|
|||
}
|
||||
|
||||
private void serializeUniqueConstraint(Unique unique) throws SAXException {
|
||||
if (StringUtils.isNotEmpty(unique.getName())) {
|
||||
//TODO JRB: If the spec is modified to use a name attribute
|
||||
// remove the element def and uncomment the attribute def
|
||||
startElement("name");
|
||||
addText(unique.getName());
|
||||
endElement("name");
|
||||
// addAttribute("name", unique.getName());
|
||||
}
|
||||
startElement("unique-constraint");
|
||||
Column[] columns = unique.getColumns();
|
||||
for (Column column:columns) {
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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.unique;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.SecondaryTable;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
/**
|
||||
* Data structures for testing unique constraint settings on ORM Annotations.
|
||||
* @UniqueConstraint annotation is declared at class-level with
|
||||
* @Table,
|
||||
* @SecondaryTable annotations
|
||||
* and at field-level with
|
||||
* @JoinTable annotation.
|
||||
* also with
|
||||
* @Column(unique=true) on single column.
|
||||
*
|
||||
* The columns included in unique constraint must be non-nullable. This is
|
||||
* recommended that the non-nullability of the column is explictly set by the
|
||||
* user, though the implementation forces a column to non-nullable as a column
|
||||
* is included in a unique constraint.
|
||||
*
|
||||
* The name of the constraint is generated by the implementation as JPA ORM
|
||||
* specification has not allowed to specify a name for the constraint via the
|
||||
* annotation or XML descriptor. Some databases allow two constraints having the
|
||||
* same name but applied to different tables, while some other databases do not.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Table(name="N_UNIQUE_A",
|
||||
uniqueConstraints={@UniqueConstraint(name="uca_f1_f2", columnNames={"f1","f2"}),
|
||||
@UniqueConstraint(name="uca_f3_f4", columnNames={"f3","f4"})})
|
||||
@SecondaryTable(name="N_UNIQUE_SECONDARY",
|
||||
uniqueConstraints=@UniqueConstraint(name="uca_sf1", columnNames={"sf1"}))
|
||||
|
||||
public class NamedUniqueA {
|
||||
@Id
|
||||
private int aid;
|
||||
|
||||
// Same named field in UniqueB also is defined as unique
|
||||
@Column(unique=true, nullable=false)
|
||||
private int f1;
|
||||
|
||||
@Column(nullable=false)
|
||||
private int f2;
|
||||
|
||||
@Column(nullable=false)
|
||||
private int f3;
|
||||
|
||||
@Column(nullable=false)
|
||||
private int f4;
|
||||
|
||||
private int f5;
|
||||
private int f6;
|
||||
|
||||
@Column(table="N_UNIQUE_SECONDARY", nullable=false)
|
||||
private short sf1;
|
||||
|
||||
@Column(table="N_UNIQUE_SECONDARY")
|
||||
private short sf2;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name="N_UNIQUE_JOINTABLE",
|
||||
joinColumns={@JoinColumn(name="FK_A", nullable=false,
|
||||
referencedColumnName="aid")},
|
||||
inverseJoinColumns={@JoinColumn(name="FK_B", nullable=false,
|
||||
referencedColumnName="bid")},
|
||||
uniqueConstraints=@UniqueConstraint(name="uca_fka_fkb", columnNames={"FK_A","FK_B"}))
|
||||
private Collection<NamedUniqueB> bs;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.unique;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name="N_UNIQUE_B",
|
||||
uniqueConstraints={@UniqueConstraint(name="ucb_f1_f2", columnNames={"f1","f2"})})
|
||||
public class NamedUniqueB {
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.TABLE, generator="namedTestGenerator")
|
||||
@TableGenerator(name="namedTestGenerator", table="N_UNIQUE_GENERATOR",
|
||||
pkColumnName="GEN1", valueColumnName="GEN2",
|
||||
uniqueConstraints={@UniqueConstraint(name="ucb_gen1_gen2", columnNames={"GEN1","GEN2"})})
|
||||
private int bid;
|
||||
|
||||
// Same named field in UniqueA also is defined as unique
|
||||
@Column(unique=true, nullable=false)
|
||||
private int f1;
|
||||
|
||||
@Column(nullable=false)
|
||||
private int f2;
|
||||
|
||||
@CollectionTable(name="N_U_COLL_TBL", uniqueConstraints=
|
||||
{@UniqueConstraint(name="ucb_f3", columnNames="f3")})
|
||||
@ElementCollection
|
||||
@Column(name="f3", nullable=false)
|
||||
private Set<String> f3;
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.unique;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
|
||||
import org.apache.openjpa.persistence.jdbc.SQLSniffer;
|
||||
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||
|
||||
public class TestNamedUniqueConstraint extends SQLListenerTestCase {
|
||||
@Override
|
||||
public void setUp(Object... props) {
|
||||
super.setUp(DROP_TABLES, NamedUniqueA.class, NamedUniqueB.class);
|
||||
}
|
||||
|
||||
public void testMapping() {
|
||||
|
||||
// If the database does not support unique constraints, exit
|
||||
if (!supportsUniqueConstraints())
|
||||
return;
|
||||
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
// The above should trigger schema definition
|
||||
|
||||
List<String> sqls = super.sql;
|
||||
|
||||
assertSQLFragnments(sqls, "CREATE TABLE N_UNIQUE_A",
|
||||
"uca_f1_f2 UNIQUE .*\\(f1, f2\\)",
|
||||
"uca_f3_f4 UNIQUE .*\\(f3, f4\\).*");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE N_UNIQUE_B",
|
||||
"ucb_f1_f2 UNIQUE .*\\(f1, f2\\).*");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE N_UNIQUE_SECONDARY",
|
||||
"uca_sf1 UNIQUE .*\\(sf1\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE N_UNIQUE_GENERATOR",
|
||||
"ucb_gen1_gen2 UNIQUE .*\\(GEN1, GEN2\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE N_UNIQUE_JOINTABLE",
|
||||
"uca_fka_fkb UNIQUE .*\\(FK_A, FK_B\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE N_U_COLL_TBL",
|
||||
"ucb_f3 UNIQUE .*\\(f3\\).*");
|
||||
}
|
||||
|
||||
private boolean supportsUniqueConstraints() {
|
||||
OpenJPAEntityManagerFactorySPI emfs = (OpenJPAEntityManagerFactorySPI)emf;
|
||||
JDBCConfiguration jdbccfg = (JDBCConfiguration)emfs.getConfiguration();
|
||||
return jdbccfg.getDBDictionaryInstance().supportsUniqueConstraints;
|
||||
}
|
||||
|
||||
void assertSQLFragnments(List<String> list, String... keys) {
|
||||
if (SQLSniffer.matches(list, keys))
|
||||
return;
|
||||
fail("None of the following " + sql.size() + " SQL \r\n" +
|
||||
toString(sql) + "\r\n contains all keys \r\n"
|
||||
+ toString(Arrays.asList(keys)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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.unique;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
|
||||
import org.apache.openjpa.persistence.jdbc.SQLSniffer;
|
||||
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||
|
||||
public class TestNamedUniqueConstraintWithXMLDescriptor extends SQLListenerTestCase {
|
||||
@Override
|
||||
public void setUp(Object... props) {
|
||||
super.setUp(DROP_TABLES, NamedUniqueA.class, NamedUniqueB.class);
|
||||
}
|
||||
|
||||
protected String getPersistenceUnitName() {
|
||||
return "NamedUniqueConstraintTest";
|
||||
}
|
||||
|
||||
public void testMapping() {
|
||||
|
||||
// If the database does not support unique constraints, exit
|
||||
if (!supportsUniqueConstraints())
|
||||
return;
|
||||
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
// The above should trigger schema definition
|
||||
|
||||
List<String> sqls = super.sql;
|
||||
|
||||
assertSQLFragnments(sqls, "CREATE TABLE NX_UNIQUE_A",
|
||||
"ucxa_f1_f2 UNIQUE .*\\(f1x, f2x\\)",
|
||||
"ucxa_f3_f4 UNIQUE .*\\(f3x, f4x\\).*");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE NX_UNIQUE_B",
|
||||
"ucxb_f1_f2 UNIQUE .*\\(f1x, f2x\\).*");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE NX_UNIQUE_SECONDARY",
|
||||
"ucxa_sf1 UNIQUE .*\\(sf1x\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE NX_UNIQUE_GENERATOR",
|
||||
"ucxb_gen1_gen2 UNIQUE .*\\(GEN1_XML, GEN2_XML\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE NX_UNIQUE_JOINTABLE",
|
||||
"ucxa_fka_fkb UNIQUE .*\\(FK_A_XML, FK_B_XML\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE NX_U_COLL_TBL",
|
||||
"ucxb_f3 UNIQUE .*\\(f3x\\).*");
|
||||
|
||||
}
|
||||
|
||||
private boolean supportsUniqueConstraints() {
|
||||
OpenJPAEntityManagerFactorySPI emfs = (OpenJPAEntityManagerFactorySPI)emf;
|
||||
JDBCConfiguration jdbccfg = (JDBCConfiguration)emfs.getConfiguration();
|
||||
return jdbccfg.getDBDictionaryInstance().supportsUniqueConstraints;
|
||||
}
|
||||
|
||||
void assertSQLFragnments(List<String> list, String... keys) {
|
||||
if (SQLSniffer.matches(list, keys))
|
||||
return;
|
||||
fail("None of the following " + sql.size() + " SQL \r\n" +
|
||||
toString(sql) + "\r\n contains all keys \r\n"
|
||||
+ toString(Arrays.asList(keys)));
|
||||
}
|
||||
}
|
|
@ -220,5 +220,16 @@
|
|||
value="buildSchema"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="NamedUniqueConstraintTest" transaction-type="RESOURCE_LOCAL">
|
||||
<description>PU for order named unique constraint testing</description>
|
||||
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
|
||||
<mapping-file>org/apache/openjpa/persistence/jdbc/unique/named-constraint-orm.xml</mapping-file>
|
||||
<class>org.apache.openjpa.persistence.jdbc.unique.NamedUniqueA</class>
|
||||
<class>org.apache.openjpa.persistence.jdbc.unique.NamedUniqueB</class>
|
||||
<properties>
|
||||
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
</persistence>
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence orm_2_0.xsd"
|
||||
version="2.0">
|
||||
|
||||
<persistence-unit-metadata>
|
||||
<xml-mapping-metadata-complete/>
|
||||
</persistence-unit-metadata>
|
||||
|
||||
|
||||
<package>org.apache.openjpa.persistence.jdbc.unique</package>
|
||||
<entity name="NamedUniqueA" class="NamedUniqueA">
|
||||
<table name="NX_UNIQUE_A">
|
||||
<unique-constraint>
|
||||
<name>ucxa_f1_f2</name>
|
||||
<column-name>f1x</column-name>
|
||||
<column-name>f2x</column-name>
|
||||
</unique-constraint>
|
||||
<unique-constraint>
|
||||
<name>ucxa_f3_f4</name>
|
||||
<column-name>f3x</column-name>
|
||||
<column-name>f4x</column-name>
|
||||
</unique-constraint>
|
||||
</table>
|
||||
<secondary-table name="NX_UNIQUE_SECONDARY">
|
||||
<unique-constraint>
|
||||
<name>ucxa_sf1</name>
|
||||
<column-name>sf1x</column-name>
|
||||
</unique-constraint>
|
||||
</secondary-table>
|
||||
<attributes>
|
||||
<id name="aid">
|
||||
</id>
|
||||
<basic name="f1">
|
||||
<column name="f1x" unique="true"/>
|
||||
</basic>
|
||||
<basic name="f2">
|
||||
<column name="f2x"/>
|
||||
</basic>
|
||||
<basic name="f3">
|
||||
<column name="f3x"/>
|
||||
</basic>
|
||||
<basic name="f4">
|
||||
<column name="f4x"/>
|
||||
</basic>
|
||||
<basic name="f5">
|
||||
<column name="f5x"/>
|
||||
</basic>
|
||||
<basic name="f6">
|
||||
<column name="f6x"/>
|
||||
</basic>
|
||||
<basic name="sf1">
|
||||
<column name="sf1x" table="NX_UNIQUE_SECONDARY" />
|
||||
</basic>
|
||||
<basic name="sf2">
|
||||
<column name="sf2x" table="NX_UNIQUE_SECONDARY" />
|
||||
</basic>
|
||||
|
||||
<many-to-many name="bs">
|
||||
<join-table name="NX_UNIQUE_JOINTABLE">
|
||||
<join-column name="FK_A_XML" referenced-column-name="aid" nullable="false"/>
|
||||
<inverse-join-column name="FK_B_XML" referenced-column-name="bid" nullable="false"/>
|
||||
<unique-constraint>
|
||||
<name>ucxa_fka_fkb</name>
|
||||
<column-name>FK_A_XML</column-name>
|
||||
<column-name>FK_B_XML</column-name>
|
||||
</unique-constraint>
|
||||
</join-table>
|
||||
</many-to-many>
|
||||
</attributes>
|
||||
</entity>
|
||||
|
||||
<entity name="NamedUniqueB" class="NamedUniqueB">
|
||||
<table name="NX_UNIQUE_B">
|
||||
<unique-constraint>
|
||||
<name>ucxb_f1_f2</name>
|
||||
<column-name>f1x</column-name>
|
||||
<column-name>f2x</column-name>
|
||||
</unique-constraint>
|
||||
</table>
|
||||
<attributes>
|
||||
<id name="bid">
|
||||
<generated-value strategy="TABLE"
|
||||
generator="testGeneratorXML" />
|
||||
<table-generator name="testGeneratorXML"
|
||||
table="NX_UNIQUE_GENERATOR" pk-column-name="GEN1_XML"
|
||||
value-column-name="GEN2_XML">
|
||||
<unique-constraint>
|
||||
<name>ucxb_gen1_gen2</name>
|
||||
<column-name>GEN1_XML</column-name>
|
||||
<column-name>GEN2_XML</column-name>
|
||||
</unique-constraint>
|
||||
</table-generator>
|
||||
</id>
|
||||
<basic name="f1">
|
||||
<column name="f1x" unique="true"/>
|
||||
</basic>
|
||||
<basic name="f2">
|
||||
<column name="f2x"/>
|
||||
</basic>
|
||||
<element-collection name="f3">
|
||||
<column name="f3x" nullable="false"/>
|
||||
<collection-table name="NX_U_COLL_TBL">
|
||||
<unique-constraint>
|
||||
<name>ucxb_f3</name>
|
||||
<column-name>f3x</column-name>
|
||||
</unique-constraint>
|
||||
</collection-table>
|
||||
</element-collection>
|
||||
</attributes>
|
||||
</entity>
|
||||
</entity-mappings>
|
|
@ -363,11 +363,17 @@ is sent to the database before the SQL inserting <literal>B</literal> to avoid a
|
|||
unique constraint violation.
|
||||
</para>
|
||||
<para>
|
||||
<classname>UniqueConstraint</classname> has a single property:
|
||||
<classname>UniqueConstraint</classname> has these properties:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>String name</literal>: The name of the constraint. OpenJPA will choose
|
||||
a name if you do not provide one, or will create an anonymous constraint.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>String[] columnNames</literal>: The names of the columns the
|
||||
constraint spans.
|
||||
</para>
|
||||
|
@ -390,7 +396,7 @@ column of the <literal>ART</literal> table:
|
|||
</para>
|
||||
<programlisting>
|
||||
@Entity
|
||||
@Table(name="ART", uniqueConstraints=@Unique(columnNames="TITLE"))
|
||||
@Table(name="ART", uniqueConstraints=@UniqueConstraint(name="TITLE_CNSTR", columnNames="TITLE"))
|
||||
public class Article {
|
||||
...
|
||||
}
|
||||
|
@ -402,6 +408,7 @@ The same metadata expressed in XML form:
|
|||
<entity class="org.mag.Article">
|
||||
<table name="ART">
|
||||
<unique-constraint>
|
||||
<name>TITLE_CNSTR</name>
|
||||
<column-name>TITLE</column-name>
|
||||
</unique-constraint>
|
||||
</table>
|
||||
|
|
Loading…
Reference in New Issue