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 60d759892..608d9c221 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 @@ -330,9 +330,15 @@ public class ClassMappingInfo _uniques.add(unique); } + public Unique[] getUniques() { + return (_uniques == null) ? new Unique[0] : + (Unique[])_uniques.toArray(new Unique[_uniques.size()]); + } + public Unique[] getUniques(ClassMapping cm, boolean adapt) { if (_uniques == null || _uniques.isEmpty()) return new Unique[0]; + Iterator uniqueConstraints = _uniques.iterator(); Table table = cm.getTable(); Collection result = new ArrayList(); diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java index 0a527829a..c62579958 100644 --- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java +++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java @@ -32,6 +32,7 @@ enum MappingTag { ATTR_OVERRIDE, ATTR_OVERRIDES, COL, + COLUMN_NAME, COLUMN_RESULT, DISCRIM_COL, DISCRIM_VAL, diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java index 04d7dd738..3fb45a90c 100644 --- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java +++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java @@ -69,6 +69,7 @@ public class XMLPersistenceMappingParser _elems.put("association-override", ASSOC_OVERRIDE); _elems.put("attribute-override", ATTR_OVERRIDE); _elems.put("column", COL); + _elems.put("column-name", COLUMN_NAME); _elems.put("column-result", COLUMN_RESULT); _elems.put("discriminator-column", DISCRIM_COL); _elems.put("discriminator-value", DISCRIM_VAL); @@ -85,6 +86,7 @@ public class XMLPersistenceMappingParser _elems.put("table", TABLE); _elems.put("table-generator", TABLE_GEN); _elems.put("temporal", TEMPORAL); + _elems.put("unique-constraint", UNIQUE); } private static final Localizer _loc = Localizer.forPackage @@ -220,8 +222,7 @@ public class XMLPersistenceMappingParser ret = startTableGenerator(attrs); break; case UNIQUE: - getLog().warn(_loc.get("unique-constraints", currentElement())); - ret = false; + ret = startUniqueConstraint(attrs); break; case TEMPORAL: case ENUMERATED: @@ -239,6 +240,9 @@ public class XMLPersistenceMappingParser case COLUMN_RESULT: ret = startColumnResult(attrs); break; + case COLUMN_NAME: + ret = true; + break; default: ret = false; } @@ -277,6 +281,12 @@ public class XMLPersistenceMappingParser case ENTITY_RESULT: endEntityResult(); break; + case UNIQUE: + endUniqueConstraint(); + break; + case COLUMN_NAME: + endColumnName(); + break; } } @@ -846,6 +856,52 @@ public class XMLPersistenceMappingParser return true; } + /** + * Starts processing <unique-constraint> provided the tag occurs + * within a ClassMapping element and not within a secondary + * table. + * Pushes the Unique element in the stack. + */ + private boolean startUniqueConstraint(Attributes attrs) + throws SAXException { + Object current = currentElement(); + if (current instanceof ClassMapping && _secondaryTable == null) { + Unique unique = new Unique(); + pushElement(unique); + return true; + } + return false; + } + + /** + * Ends processing <unique-constraint> provided the tag occurs + * within a ClassMapping element and not within a secondary + * table. The stack is popped and the Unique element is added to the + * ClassMappingInfo. + */ + private void endUniqueConstraint() { + Unique unique = (Unique)popElement(); + Object current = currentElement(); + if (current instanceof ClassMapping && _secondaryTable == null) + ((ClassMapping)current).getMappingInfo().addUnique(unique); + } + + /** + * Ends processing <column-name> tag by adding the column name in + * the current Unique element that resides in the top of the stack. + */ + private boolean endColumnName() { + Object current = currentElement(); + if (current instanceof Unique) { + Unique unique = (Unique)current; + Column column = new Column(); + column.setName(this.currentText()); + unique.addColumn(column); + return true; + } + return false; + } + /** * Track unique column settings. */ diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingSerializer.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingSerializer.java index 755020432..500b76a53 100644 --- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingSerializer.java +++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingSerializer.java @@ -42,6 +42,7 @@ import org.apache.openjpa.jdbc.meta.strats.FlatClassStrategy; import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy; import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy; import org.apache.openjpa.jdbc.schema.Column; +import org.apache.openjpa.jdbc.schema.Unique; import org.apache.openjpa.jdbc.sql.DBDictionary; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; @@ -181,9 +182,10 @@ public class XMLPersistenceMappingSerializer ClassMapping cls = (ClassMapping) mapping; ClassMappingInfo info = cls.getMappingInfo(); serializeTable(info.getTableName(), "table", Strings - .getClassName(mapping.getDescribedType()), null); + .getClassName(mapping.getDescribedType()), null, + info.getUniques()); for (String second : info.getSecondaryTableNames()) - serializeTable(second, "secondary-table", null, info); + serializeTable(second, "secondary-table", null, info, null); serializeColumns(info, ColType.PK_JOIN, null); } @@ -218,14 +220,15 @@ public class XMLPersistenceMappingSerializer * in the given {@link ClassMappingInfo}. */ private void serializeTable(String table, String elementName, - String defaultName, ClassMappingInfo secondaryInfo) + String defaultName, ClassMappingInfo secondaryInfo, Unique[] uniques) throws SAXException { List cols = null; if (secondaryInfo != null) cols = (List) secondaryInfo.getSecondaryTableJoinColumns (table); - boolean print = cols != null && cols.size() > 0; + boolean print = (cols != null && cols.size() > 0) || + (uniques !=null || uniques.length > 0); if (table != null && (defaultName == null || !defaultName.equals(table))) { print = true; @@ -243,6 +246,9 @@ public class XMLPersistenceMappingSerializer for (Column col : cols) serializeColumn(col, ColType.PK_JOIN, null, false); } + if (uniques != null) + for (Unique unique: uniques) + serializeUniqueConstraint(unique); endElement(elementName); } } @@ -509,6 +515,17 @@ public class XMLPersistenceMappingSerializer } } + private void serializeUniqueConstraint(Unique unique) throws SAXException { + startElement("unique-constraint"); + Column[] columns = unique.getColumns(); + for (Column column:columns) { + startElement("column-name"); + addText(column.getName()); + endElement("column-name"); + } + endElement("unique-constraint"); + } + @Override protected SerializationComparator newSerializationComparator() { return new MappingSerializationComparator();