mirror of https://github.com/apache/openjpa.git
OPENJPA-340: UniqueConstraint supported via XML Descriptors
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@672406 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ff4a96e707
commit
6868b1cc4a
|
@ -20,6 +20,7 @@ package org.apache.openjpa.jdbc.meta;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
@ -212,9 +213,17 @@ public class ClassMappingInfo
|
|||
}
|
||||
return (cols == null) ? Collections.EMPTY_LIST : cols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Secondary table of given name to this mapping. A secondary table
|
||||
* must be known before unique constraints are added to a Secondary table.
|
||||
*/
|
||||
public void addSecondaryTable(String second) {
|
||||
setSecondaryTableJoinColumns(second, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare the given class-level join.
|
||||
* Declare the given class-level join to the named (secondary) table.
|
||||
*/
|
||||
public void setSecondaryTableJoinColumns(String tableName, List cols) {
|
||||
if (cols == null)
|
||||
|
@ -419,7 +428,7 @@ public class ClassMappingInfo
|
|||
if (!table.containsColumn(columnName)) {
|
||||
throw new UserException(_loc.get("unique-missing-column",
|
||||
new Object[]{cm, columnName, tableName,
|
||||
table.getColumnNames()}));
|
||||
Arrays.toString(table.getColumnNames())}));
|
||||
}
|
||||
Column uniqueColumn = table.getColumn(columnName);
|
||||
uniqueColumns[i] = uniqueColumn;
|
||||
|
|
|
@ -928,6 +928,11 @@ public abstract class MappingInfo
|
|||
deferred = false;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
name = cols[0].getName();
|
||||
name = repos.getDBDictionary().getValidUniqueName(name, table);
|
||||
}
|
||||
|
||||
Unique unq = table.addUnique(name);
|
||||
unq.setDeferred(deferred);
|
||||
unq.setColumns(cols);
|
||||
|
|
|
@ -24,48 +24,83 @@ import org.apache.commons.lang.StringUtils;
|
|||
* Represents a unique constraint. It can also represent a partial constraint.
|
||||
*
|
||||
* @author Abe White
|
||||
* @author Pinaki Poddar
|
||||
*/
|
||||
public class Unique
|
||||
extends LocalConstraint {
|
||||
private boolean _isAutoSetName = false;
|
||||
/**
|
||||
* Default constructor.
|
||||
private boolean _autoNaming = false;
|
||||
|
||||
/**
|
||||
* Default constructor without a name.
|
||||
* Assumes that this constraint will set its own name automatically from
|
||||
* the names of the columns added to it.
|
||||
*/
|
||||
public Unique() {
|
||||
_isAutoSetName = true;
|
||||
_autoNaming = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Construct with given name.
|
||||
* Assumes that this constraint will not set its own name.
|
||||
*
|
||||
* @param name the name of the constraint, if any
|
||||
* @param table the table of the constraint
|
||||
*/
|
||||
public Unique(String name, Table table) {
|
||||
super(name, table);
|
||||
_autoNaming = false;
|
||||
}
|
||||
|
||||
public boolean isLogical() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given column.
|
||||
* The added column is set to non-nullable because a unique constraint
|
||||
* on the database requires that its constituent columns are NOT NULL.
|
||||
* @see Column#setNotNull(boolean)
|
||||
* If this instance is constructing its own name, then this method also
|
||||
* has the side effect of changing its own name by appending the newly
|
||||
* added column name to its own name.
|
||||
*/
|
||||
public void addColumn(Column col) {
|
||||
super.addColumn(col);
|
||||
col.setNotNull(true);
|
||||
if (_isAutoSetName && getTable() == null) {
|
||||
String pre = StringUtils.isEmpty(getName()) ? "UNQ" : getName();
|
||||
setName(pre + "_" + col.getName());
|
||||
_isAutoSetName = true;
|
||||
if (_autoNaming && getTable() == null) {
|
||||
String prefix = createPrefix();
|
||||
setName(prefix + "_" + chop(col.getName(), 4));
|
||||
_autoNaming = true;
|
||||
}
|
||||
}
|
||||
|
||||
private String createPrefix() {
|
||||
String currentName = getName();
|
||||
if (StringUtils.isEmpty(currentName)) {
|
||||
String tname = getTableName();
|
||||
if (StringUtils.isEmpty(tname))
|
||||
return "UNQ";
|
||||
else
|
||||
return "UNQ_" + chop(tname, 3);
|
||||
}
|
||||
return currentName;
|
||||
}
|
||||
|
||||
private String chop(String name, int head) {
|
||||
if (StringUtils.isEmpty(name))
|
||||
return name;
|
||||
return name.substring(0, Math.min(Math.max(1,head), name.length()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the constraint. This method cannot be called if the
|
||||
* constraint already belongs to a table.
|
||||
* constraint already belongs to a table. Calling this method also has the
|
||||
* side-effect of implying that the instance will not auto-generate its
|
||||
* name.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
super.setName(name);
|
||||
_isAutoSetName = false;
|
||||
_autoNaming = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,4 +111,13 @@ public class Unique
|
|||
public boolean equalsUnique(Unique unq) {
|
||||
return equalsLocalConstraint(unq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Affirms if this instance is currently generating its own name. No
|
||||
* mutator because auto-naming is switched off as side-effect of user
|
||||
* calling setName() directly.
|
||||
*/
|
||||
public boolean isAutoNaming() {
|
||||
return _autoNaming;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -483,8 +483,10 @@ public class AnnotationPersistenceMappingParser
|
|||
joins = new ArrayList<Column>(table.pkJoinColumns().length);
|
||||
for (PrimaryKeyJoinColumn join : table.pkJoinColumns())
|
||||
joins.add(newColumn(join));
|
||||
}
|
||||
info.setSecondaryTableJoinColumns(name, joins);
|
||||
info.setSecondaryTableJoinColumns(name, joins);
|
||||
} else {
|
||||
info.addSecondaryTable(name);
|
||||
}
|
||||
addUniqueConstraints(name, cm, info, table.uniqueConstraints());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.apache.openjpa.jdbc.meta.ClassMapping;
|
|||
import org.apache.openjpa.jdbc.meta.ClassMappingInfo;
|
||||
import org.apache.openjpa.jdbc.meta.DiscriminatorMappingInfo;
|
||||
import org.apache.openjpa.jdbc.meta.FieldMapping;
|
||||
import org.apache.openjpa.jdbc.meta.FieldMappingInfo;
|
||||
import org.apache.openjpa.jdbc.meta.MappingInfo;
|
||||
import org.apache.openjpa.jdbc.meta.MappingRepository;
|
||||
import org.apache.openjpa.jdbc.meta.QueryResultMapping;
|
||||
|
@ -359,6 +360,8 @@ public class XMLPersistenceMappingParser
|
|||
throws SAXException {
|
||||
_secondaryTable = toTableName(attrs.getValue("schema"),
|
||||
attrs.getValue("name"));
|
||||
((ClassMapping)currentElement()).getMappingInfo()
|
||||
.addSecondaryTable(_secondaryTable);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -906,18 +909,23 @@ public class XMLPersistenceMappingParser
|
|||
Unique unique = (Unique) popElement();
|
||||
Object ctx = currentElement();
|
||||
String tableName = "?";
|
||||
ClassMappingInfo info = null;
|
||||
if (ctx instanceof ClassMapping) {
|
||||
info = ((ClassMapping) ctx).getMappingInfo();
|
||||
tableName = (_secondaryTable != null) ? info.getTableName() : _secondaryTable;
|
||||
ClassMappingInfo info = ((ClassMapping) ctx).getMappingInfo();
|
||||
tableName = (_secondaryTable == null)
|
||||
? info.getTableName() : _secondaryTable;
|
||||
info.addUnique(tableName, unique);
|
||||
} else if (ctx instanceof FieldMapping) {// JoinTable
|
||||
info = ((FieldMapping)ctx).getDeclaringMapping().getMappingInfo();
|
||||
tableName = info.getTableName();
|
||||
info.addUnique(tableName, unique);
|
||||
FieldMappingInfo info = ((FieldMapping)ctx).getMappingInfo();
|
||||
info.addJoinTableUnique(unique);
|
||||
} else if (ctx instanceof SequenceMapping) {
|
||||
tableName = ((SequenceMapping)ctx).getTable();
|
||||
unique.setTableName(tableName);
|
||||
SequenceMapping seq = (SequenceMapping)ctx;
|
||||
unique.setTableName(seq.getTable());
|
||||
Column[] uniqueColumns = unique.getColumns();
|
||||
String[] columnNames = new String[uniqueColumns.length];
|
||||
int i = 0;
|
||||
for (Column uniqueColumn : uniqueColumns)
|
||||
columnNames[i++] = uniqueColumn.getName();
|
||||
seq.setUniqueColumns(columnNames);
|
||||
} else {
|
||||
throw new InternalException();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.regexp.RE;
|
||||
|
||||
/**
|
||||
* Utility class to verify whether a set of fragments appear in a list of
|
||||
* possible SQL statement.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class SQLSniffer {
|
||||
|
||||
private static Map<String, RE> cache = new HashMap<String, RE>();
|
||||
/**
|
||||
* Checks that the given set of regular expressions occur in at least one of
|
||||
* the given input SQL.
|
||||
*/
|
||||
public static boolean matches(List<String> SQLs, String...regexes) {
|
||||
if (SQLs == null || regexes == null)
|
||||
return false;
|
||||
for (String sql : SQLs) {
|
||||
boolean matched = true;
|
||||
for (String key : regexes) {
|
||||
RE regex = getRegularExpression(key);
|
||||
if (!regex.match(sql)) {
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matched)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static RE getRegularExpression(String regex) {
|
||||
if (cache.containsKey(regex))
|
||||
return cache.get(regex);
|
||||
RE re = new RE(regex);
|
||||
cache.put(regex, re);
|
||||
return re;
|
||||
}
|
||||
}
|
|
@ -23,12 +23,24 @@ import java.util.List;
|
|||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.apache.openjpa.persistence.jdbc.SQLSniffer;
|
||||
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||
|
||||
public class TestUnique extends SQLListenerTestCase {
|
||||
/**
|
||||
* Tests unique constraints specified via annotations for primary/secondary
|
||||
* table, sequence generator, join tables have been defined on database by
|
||||
* examining DDL statements.
|
||||
*
|
||||
* @see resources/org/apache/openjpa/persistence/jdbc/unique/orm.xml defines
|
||||
* the ORM mapping.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class TestUniqueConstraint extends SQLListenerTestCase {
|
||||
@Override
|
||||
public void setUp(Object... props) {
|
||||
super.setUp(UniqueA.class, UniqueB.class);
|
||||
super.setUp(DROP_TABLES, UniqueA.class, UniqueB.class);
|
||||
}
|
||||
|
||||
public void testMapping() {
|
||||
|
@ -40,39 +52,28 @@ public class TestUnique extends SQLListenerTestCase {
|
|||
|
||||
List<String> sqls = super.sql;
|
||||
|
||||
assertSQLFragnment(sqls, "CREATE TABLE UNIQUE_A",
|
||||
"UNIQUE (a1, a2)",
|
||||
"UNIQUE (a3, a4)");
|
||||
assertSQLFragnment(sqls, "CREATE TABLE UNIQUE_B",
|
||||
"UNIQUE (b1, b2)");
|
||||
assertSQLFragnment(sqls, "CREATE TABLE UNIQUE_SECONDARY",
|
||||
"UNIQUE (sa1)");
|
||||
assertSQLFragnment(sqls, "CREATE TABLE UNIQUE_GENERATOR",
|
||||
"UNIQUE (GEN1, GEN2)");
|
||||
assertSQLFragnment(sqls, "CREATE TABLE UNIQUE_JOINTABLE",
|
||||
"UNIQUE (UNIQUEA_AID, BS_BID)");
|
||||
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_A",
|
||||
"UNIQUE \\w*\\(a1, a2\\)",
|
||||
"UNIQUE \\w*\\(a3, a4\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_B",
|
||||
"UNIQUE \\w*\\(b1, b2\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_SECONDARY",
|
||||
"UNIQUE \\w*\\(sa1\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_GENERATOR",
|
||||
"UNIQUE \\w*\\(GEN1, GEN2\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_JOINTABLE",
|
||||
"UNIQUE \\w*\\(FK_A, FK_B\\)");
|
||||
}
|
||||
|
||||
void assertSQLFragnment(List<String> list, String...keys) {
|
||||
for (String sql : list) {
|
||||
String SQL = sql.toUpperCase();
|
||||
boolean matched = true;
|
||||
for (String key : keys) {
|
||||
String KEY = key.toUpperCase();
|
||||
if (SQL.indexOf(KEY) == -1) {
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matched)
|
||||
return;
|
||||
}
|
||||
void assertSQLFragnments(List<String> list, String... keys) {
|
||||
if (SQLSniffer.matches(list, keys))
|
||||
return;
|
||||
int i = 0;
|
||||
for (String sql : list) {
|
||||
i++;
|
||||
System.out.println(""+i+":"+sql);
|
||||
System.out.println("" + i + ":" + sql);
|
||||
}
|
||||
fail("None of the above SQL contains all keys " + Arrays.toString(keys));
|
||||
fail("None of the " + sql.size() + " SQL contains all keys "
|
||||
+ Arrays.toString(keys));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.persistence.jdbc.SQLSniffer;
|
||||
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||
|
||||
/**
|
||||
* Tests unique constraints specified via XML Descriptor for primary/secondary
|
||||
* table, sequence generator, join tables have been defined on database by
|
||||
* examining DDL statements.
|
||||
*
|
||||
* @see resources/org/apache/openjpa/persistence/jdbc/unique/orm.xml
|
||||
* defines the ORM mapping.
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class TestUniqueConstraintWithXMLDescriptor extends SQLListenerTestCase {
|
||||
@Override
|
||||
public void setUp(Object... props) {
|
||||
super.setUp(DROP_TABLES, UniqueA.class, UniqueB.class);
|
||||
}
|
||||
|
||||
protected String getPersistenceUnitName() {
|
||||
return "test-unique-constraint";
|
||||
}
|
||||
|
||||
public void testMapping() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
// The above should trigger schema definition
|
||||
|
||||
List<String> sqls = super.sql;
|
||||
assertFalse("No SQL DDL registered", sqls.isEmpty());
|
||||
|
||||
// Following verification techniques is fragile as databases DDL
|
||||
// syntax vary greatly on UNIQUE CONSTRAINT
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_A_XML",
|
||||
"UNIQUE \\w*\\(a1x, a2x\\)",
|
||||
"UNIQUE \\w*\\(a3x, a4x\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_B_XML",
|
||||
"UNIQUE \\w*\\(b1x, b2x\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_SECONDARY_XML",
|
||||
"UNIQUE \\w*\\(sa1x\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_GENERATOR_XML",
|
||||
"UNIQUE \\w*\\(GEN1_XML, GEN2_XML\\)");
|
||||
assertSQLFragnments(sqls, "CREATE TABLE UNIQUE_JOINTABLE_XML",
|
||||
"UNIQUE \\w*\\(FK_A_XML, FK_B_XML\\)");
|
||||
}
|
||||
|
||||
void assertSQLFragnments(List<String> list, String... keys) {
|
||||
if (SQLSniffer.matches(list, keys))
|
||||
return;
|
||||
int i = 0;
|
||||
for (String sql : list) {
|
||||
i++;
|
||||
System.out.println("" + i + ":" + sql);
|
||||
}
|
||||
fail("None of the " + sql.size() + " SQL contains all keys "
|
||||
+ Arrays.toString(keys));
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ 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;
|
||||
|
@ -72,6 +73,8 @@ public class UniqueA {
|
|||
|
||||
@ManyToMany
|
||||
@JoinTable(name="UNIQUE_JOINTABLE",
|
||||
uniqueConstraints=@UniqueConstraint(columnNames={"UNIQUEA_AID","BS_BID"}))
|
||||
joinColumns={@JoinColumn(name="FK_A", nullable=false, referencedColumnName="aid")},
|
||||
inverseJoinColumns={@JoinColumn(name="FK_B", nullable=false, referencedColumnName="bid")},
|
||||
uniqueConstraints=@UniqueConstraint(columnNames={"FK_A","FK_B"}))
|
||||
private Collection<UniqueB> bs;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public abstract class PersistenceTestCase
|
|||
* database tables should be cleared.
|
||||
*/
|
||||
protected static final Object CLEAR_TABLES = new Object();
|
||||
protected static final Object DROP_TABLES = new Object();
|
||||
|
||||
/**
|
||||
* The {@link TestResult} instance for the current test run.
|
||||
|
@ -95,6 +96,10 @@ public abstract class PersistenceTestCase
|
|||
map.put("openjpa.jdbc.SynchronizeMappings",
|
||||
"buildSchema(ForeignKeys=true,"
|
||||
+ "SchemaAction='add,deleteTableContents')");
|
||||
} else if (props[i] == DROP_TABLES) {
|
||||
map.put("openjpa.jdbc.SynchronizeMappings",
|
||||
"buildSchema(ForeignKeys=true,"
|
||||
+ "SchemaAction='drop,add')");
|
||||
} else if (props[i] instanceof Class)
|
||||
types.add((Class) props[i]);
|
||||
else if (props[i] != null)
|
||||
|
|
|
@ -88,5 +88,12 @@
|
|||
<property name="openjpa.jdbc.SynchronizeMappings"
|
||||
value="buildSchema(ForeignKeys=true)"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="test-unique-constraint">
|
||||
<mapping-file>org/apache/openjpa/persistence/jdbc/unique/orm.xml</mapping-file>
|
||||
<class>org.apache.openjpa.persistence.jdbc.unique.UniqueA</class>
|
||||
<class>org.apache.openjpa.persistence.jdbc.unique.UniqueB</class>
|
||||
</persistence-unit>
|
||||
|
||||
</persistence>
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
<?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 orm_1_0.xsd"
|
||||
version="1.0">
|
||||
|
||||
<persistence-unit-metadata>
|
||||
<xml-mapping-metadata-complete>
|
||||
</xml-mapping-metadata-complete>
|
||||
</persistence-unit-metadata>
|
||||
|
||||
|
||||
<package>org.apache.openjpa.persistence.jdbc.unique</package>
|
||||
<entity name="UniqueA" class="UniqueA">
|
||||
<table name="UNIQUE_A_XML">
|
||||
<unique-constraint>
|
||||
<column-name>a1x</column-name>
|
||||
<column-name>a2x</column-name>
|
||||
</unique-constraint>
|
||||
<unique-constraint>
|
||||
<column-name>a3x</column-name>
|
||||
<column-name>a4x</column-name>
|
||||
</unique-constraint>
|
||||
</table>
|
||||
<secondary-table name="UNIQUE_SECONDARY_XML">
|
||||
<unique-constraint>
|
||||
<column-name>sa1x</column-name>
|
||||
</unique-constraint>
|
||||
</secondary-table>
|
||||
<attributes>
|
||||
<id name="aid">
|
||||
</id>
|
||||
<basic name="a1">
|
||||
<column name="a1x"/>
|
||||
</basic>
|
||||
<basic name="a2">
|
||||
<column name="a2x"/>
|
||||
</basic>
|
||||
<basic name="a3">
|
||||
<column name="a3x"/>
|
||||
</basic>
|
||||
<basic name="a4">
|
||||
<column name="a4x"/>
|
||||
</basic>
|
||||
<basic name="a5">
|
||||
<column name="a5x"/>
|
||||
</basic>
|
||||
<basic name="a6">
|
||||
<column name="a6x"/>
|
||||
</basic>
|
||||
|
||||
<basic name="sa1">
|
||||
<column name="sa1x" table="UNIQUE_SECONDARY_XML" />
|
||||
</basic>
|
||||
<basic name="sa2">
|
||||
<column name="sa2x" table="UNIQUE_SECONDARY_XML" />
|
||||
</basic>
|
||||
|
||||
<many-to-many name="bs">
|
||||
<join-table name="UNIQUE_JOINTABLE_XML">
|
||||
<join-column name="FK_A_XML" referenced-column-name="aid" nullable="false">
|
||||
</join-column>
|
||||
<inverse-join-column name="FK_B_XML" referenced-column-name="bid" nullable="false">
|
||||
</inverse-join-column>
|
||||
<unique-constraint>
|
||||
<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="UniqueB" class="UniqueB">
|
||||
<table name="UNIQUE_B_XML">
|
||||
<unique-constraint>
|
||||
<column-name>b1x</column-name>
|
||||
<column-name>b2x</column-name>
|
||||
</unique-constraint>
|
||||
</table>
|
||||
<attributes>
|
||||
<id name="bid">
|
||||
<generated-value strategy="TABLE"
|
||||
generator="testGeneratorXML" />
|
||||
<table-generator name="testGeneratorXML"
|
||||
table="UNIQUE_GENERATOR_XML" pk-column-name="GEN1_XML"
|
||||
value-column-name="GEN2_XML">
|
||||
<unique-constraint>
|
||||
<column-name>GEN1_XML</column-name>
|
||||
<column-name>GEN2_XML</column-name>
|
||||
</unique-constraint>
|
||||
</table-generator>
|
||||
</id>
|
||||
<basic name="b1">
|
||||
<column name="b1x"/>
|
||||
</basic>
|
||||
<basic name="b2">
|
||||
<column name="b2x"/>
|
||||
</basic>
|
||||
</attributes>
|
||||
</entity>
|
||||
</entity-mappings>
|
||||
|
||||
|
Loading…
Reference in New Issue