diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java index 325a3022d..7209c59d2 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java @@ -36,6 +36,8 @@ import org.apache.openjpa.jdbc.schema.ColumnIO; import org.apache.openjpa.jdbc.schema.ForeignKey; import org.apache.openjpa.jdbc.schema.Schemas; import org.apache.openjpa.jdbc.schema.Table; +import org.apache.openjpa.jdbc.schema.Unique; +import org.apache.openjpa.jdbc.schema.XMLSchemaParser; import org.apache.openjpa.jdbc.sql.Joins; import org.apache.openjpa.jdbc.sql.Result; import org.apache.openjpa.jdbc.sql.RowManager; @@ -793,6 +795,44 @@ public class ClassMapping _cols[i].setFlag(Column.FLAG_DIRECT_UPDATE, true); } } + mapUniqueConstraints(); + } + + /** + * Adds unique constraints to the mapped table. + * + */ + void mapUniqueConstraints() { + Log log = getRepository().getLog(); + Collection uniqueInfos = _info.getUniqueConstraints(); + if (uniqueInfos == null || uniqueInfos.isEmpty()) + return; + Iterator iter = uniqueInfos.iterator(); + Table table = getTable(); + int i = 1; + while (iter.hasNext()) { + XMLSchemaParser.UniqueInfo uniqueInfo = + (XMLSchemaParser.UniqueInfo)iter.next(); + if (uniqueInfo.cols == null || uniqueInfo.cols.isEmpty()) + continue; + String constraintName = table.getName() + "_UNIQUE_" + i; + i++; + Unique uniqueConstraint = table.addUnique(constraintName); + Iterator uniqueColumnNames = uniqueInfo.cols.iterator(); + while (uniqueColumnNames.hasNext()) { + String uniqueColumnName = (String)uniqueColumnNames.next(); + Column uniqueColumn = table.getColumn(uniqueColumnName); + if (uniqueColumn != null) { + uniqueConstraint.addColumn(uniqueColumn); + } else { + table.removeUnique(uniqueConstraint); + if (log.isWarnEnabled()) + log.warn(_loc.get("missing-unique-column", this, + table.getName(), uniqueColumnName)); + break; + } + } + } } /** diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java index 88352e249..66314ce04 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java @@ -21,6 +21,9 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Collection; +import java.util.ArrayList; +import java.util.Arrays; import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy; import org.apache.openjpa.jdbc.schema.Column; @@ -28,6 +31,7 @@ import org.apache.openjpa.jdbc.schema.ForeignKey; import org.apache.openjpa.jdbc.schema.Schema; import org.apache.openjpa.jdbc.schema.SchemaGroup; import org.apache.openjpa.jdbc.schema.Table; +import org.apache.openjpa.jdbc.schema.XMLSchemaParser; import org.apache.openjpa.lib.meta.SourceTracker; import org.apache.openjpa.lib.xml.Commentable; @@ -51,6 +55,7 @@ public class ClassMappingInfo private File _file = null; private int _srcType = SRC_OTHER; private String[] _comments = null; + private Collection _uniqueConstraints = null;//XMLSchemaParser.UniqueInfo /** * The described class name. @@ -275,7 +280,7 @@ public class ClassMappingInfo : cls.getStrategy().getAlias(); if (strat != null && (cls.getPCSuperclass() != null || !FullClassStrategy.ALIAS.equals(strat))) - setStrategy(strat); + setStrategy(strat); } public boolean hasSchemaComponents() { @@ -308,8 +313,22 @@ public class ClassMappingInfo _seconds.put(key, cinfo._seconds.get(key)); } } + if (cinfo._uniqueConstraints != null) + _uniqueConstraints = new ArrayList(cinfo._uniqueConstraints); } + public void addUniqueConstaint(String[] columnNames) { + if (_uniqueConstraints == null) + _uniqueConstraints = new ArrayList(); + XMLSchemaParser.UniqueInfo uniqueInfo = new XMLSchemaParser.UniqueInfo(); + uniqueInfo.cols = Arrays.asList(columnNames); + _uniqueConstraints.add(uniqueInfo); + } + + public Collection getUniqueConstraints() { + return _uniqueConstraints; + } + public File getSourceFile() { return _file; } 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 3bccecec5..78ccfd145 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 @@ -560,6 +560,27 @@ public class SchemaTool { } } + // Unique Constraints on group of columns + Unique[] uniques; + for (int i = 0; i < schemas.length; i++) { + tabs = schemas[i].getTables(); + for (int j = 0; j < tabs.length; j++) { + // create unique constraints only on new tables + if (!newTables.contains(tabs[j])) + continue; + + uniques = tabs[j].getUniques(); + if (uniques == null || uniques.length == 0) + continue; + dbTable = db.findTable(tabs[j]); + if (dbTable == null) + continue; + for (int k = 0; k < uniques.length; k++) { + dbTable.importUnique(uniques[k]); + } + } + } + // foreign keys ForeignKey[] fks; ForeignKey fk; diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/XMLSchemaParser.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/XMLSchemaParser.java index 87582b41e..1ef150fb5 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/XMLSchemaParser.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/XMLSchemaParser.java @@ -579,7 +579,7 @@ public class XMLSchemaParser /** * Used to hold unique constraint info before it is resolved. */ - private static class UniqueInfo { + public static class UniqueInfo { public Unique unq = null; public Collection cols = new LinkedList(); diff --git a/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/localizer.properties b/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/localizer.properties index d777e37d3..b14ec6027 100644 --- a/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/localizer.properties +++ b/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/localizer.properties @@ -401,3 +401,6 @@ untraversable-path: Result path "{2}" in result type "{1}" of mapping "{0}" \ attempts to traverse through a non-relation field. num-cols-path: Result path "{2}" in result type "{1}" of mapping "{0}" \ attempts to map a field that does not have exactly 1 column. +missing-unique-column: A unique constraint includes a column "{2}" specified \ + in mapping of class "{0}" to table "{1}". However, the column does not \ + exist in "{1}" table. This constraint will not be defined in the schema. diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java index e3f1c8186..8cdf67091 100644 --- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java +++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java @@ -47,6 +47,7 @@ import javax.persistence.SqlResultSetMappings; import javax.persistence.Table; import javax.persistence.TableGenerator; import javax.persistence.Temporal; +import javax.persistence.UniqueConstraint; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.jdbc.conf.JDBCConfiguration; @@ -459,10 +460,9 @@ public class AnnotationPersistenceMappingParser if (tableName != null) cm.getMappingInfo().setTableName(tableName); - //### EJB3 - Log log = getLog(); - if (table.uniqueConstraints().length > 0 && log.isWarnEnabled()) - log.warn(_loc.get("unique-constraints", cm)); + for (UniqueConstraint unique:table.uniqueConstraints()) { + ((ClassMappingInfo)cm.getMappingInfo()).addUniqueConstaint(unique.columnNames()); + } } /**