This is an automated email from the ASF dual-hosted git repository.

solomax pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git


The following commit(s) were added to refs/heads/master by this push:
     new cb20dd6  [OPENJPA-2777] Javax index (#39)
cb20dd6 is described below

commit cb20dd6b95a07fe87bf46a2c33580322d0b11cd0
Author: Maxim Solodovnik <solomax...@gmail.com>
AuthorDate: Tue Mar 5 20:44:49 2019 +0700

    [OPENJPA-2777] Javax index (#39)
    
    [OPENJPA-2777] javax.persistense.Index can be used on Table annotation
---
 .../org/apache/openjpa/jdbc/meta/ClassMapping.java |   1 +
 .../apache/openjpa/jdbc/meta/ClassMappingInfo.java | 126 ++++++++++++++++-----
 .../apache/openjpa/jdbc/meta/localizer.properties  |   5 +
 .../jdbc/AnnotationPersistenceMappingParser.java   |  41 ++++++-
 .../openjpa/persistence/jdbc/localizer.properties  |   4 +
 .../jdbc/annotations/EntityWithIndices.java        |  76 +++++++++++++
 .../persistence/jdbc/annotations/TestIndices.java  |  64 +++++++++++
 7 files changed, 286 insertions(+), 31 deletions(-)

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 a1a387f..1e35054 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
@@ -903,6 +903,7 @@ public class ClassMapping
         // once columns are resolved, resolve unique constraints as they need
         // the columns be resolved
         _info.getUniques(this, true);
+        _info.getIndices(this, true);
     }
 
     /**
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 0cad85d..60cc2a0 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
@@ -34,6 +34,7 @@ import 
org.apache.openjpa.jdbc.identifier.QualifiedDBIdentifier;
 import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy;
 import org.apache.openjpa.jdbc.schema.Column;
 import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Index;
 import org.apache.openjpa.jdbc.schema.Schema;
 import org.apache.openjpa.jdbc.schema.SchemaGroup;
 import org.apache.openjpa.jdbc.schema.Table;
@@ -77,6 +78,7 @@ public class ClassMappingInfo
     // Unique constraints indexed by primary or secondary table name
     private Map<DBIdentifier,List<Unique>> _uniques;
 
+    private Map<DBIdentifier,List<Index>> _indices = new HashMap<>();
     /**
      * The described class name.
      */
@@ -452,13 +454,21 @@ public class ClassMappingInfo
             }
         }
         if (cinfo._uniques != null) {
-               if (_uniques == null)
-                       _uniques = new HashMap<>();
-        for (Entry<DBIdentifier, List<Unique>> entry : 
cinfo._uniques.entrySet())
-                       if (!_uniques.containsKey(entry.getKey()))
-                               _uniques.put(entry.getKey(), entry.getValue());
+            if (_uniques == null) {
+                _uniques = new HashMap<>();
+            }
+            for (Entry<DBIdentifier, List<Unique>> entry : 
cinfo._uniques.entrySet()) {
+                if (!_uniques.containsKey(entry.getKey())) {
+                    _uniques.put(entry.getKey(), entry.getValue());
+                }
+            }
+        }
+        _indices.clear();
+        for (Entry<DBIdentifier, List<Index>> entry : 
cinfo._indices.entrySet()) {
+            if (!_indices.containsKey(entry.getKey())) {
+                _indices.put(entry.getKey(), entry.getValue());
+            }
         }
-
     }
 
     /**
@@ -480,24 +490,50 @@ public class ClassMappingInfo
      * @param unique the unique constraint. null means no-op.
      */
     public void addUnique(DBIdentifier table, Unique unique) {
-       if (!DBIdentifier.equal(_tableName, table) &&
-          (_seconds == null || !_seconds.containsKey(table))) {
+        if (!DBIdentifier.equal(_tableName, table) &&
+            (_seconds == null || !_seconds.containsKey(table))) {
             throw new UserException(_loc.get("unique-no-table",
                     new Object[]{table, _className, _tableName,
                     ((_seconds == null) ? "" : _seconds.keySet())}));
-       }
-       if (unique == null)
-               return;
+        }
+        if (unique == null)
+            return;
         if (_uniques == null)
             _uniques = new HashMap<>();
         unique.setTableIdentifier(table);
         List<Unique> uniques = _uniques.get(table);
         if (uniques == null) {
-               uniques = new ArrayList<>();
-               uniques.add(unique);
-               _uniques.put(table, uniques);
+            uniques = new ArrayList<>();
+            uniques.add(unique);
+            _uniques.put(table, uniques);
         } else {
-               uniques.add(unique);
+            uniques.add(unique);
+        }
+    }
+
+    /**
+     * Add index for the given table.
+     * @param table must be primary table or secondary table name added a
+     * priori to this receiver.
+     * @param idx the index. null means no-op.
+     */
+    public void addIndex(DBIdentifier table, Index idx) {
+        if (!DBIdentifier.equal(_tableName, table) &&
+           (_seconds == null || !_seconds.containsKey(table))) {
+            throw new UserException(_loc.get("index-no-table",
+                    new Object[]{table, _className, _tableName,
+                    ((_seconds == null) ? "" : _seconds.keySet())}));
+        }
+        if (idx == null)
+            return;
+        idx.setTableIdentifier(table);
+        List<Index> indices = _indices.get(table);
+        if (indices == null) {
+            indices = new ArrayList<>();
+            indices.add(idx);
+            _indices.put(table, indices);
+        } else {
+            indices.add(idx);
         }
     }
 
@@ -531,31 +567,65 @@ public class ClassMappingInfo
             return new Unique[0];
         List<Unique> result = new ArrayList<>();
         for (DBIdentifier tableName : _uniques.keySet()) {
-               List<Unique> uniqueConstraints = _uniques.get(tableName);
-               for (Unique template : uniqueConstraints) {
-                       Column[] templateColumns = template.getColumns();
+            List<Unique> uniqueConstraints = _uniques.get(tableName);
+            for (Unique template : uniqueConstraints) {
+                Column[] templateColumns = template.getColumns();
                 Column[] uniqueColumns = new Column[templateColumns.length];
                 Table table = getTable((ClassMapping)cm, tableName, adapt);
-                       for (int i=0; i<uniqueColumns.length; i++) {
+                for (int i=0; i<uniqueColumns.length; i++) {
                     DBIdentifier columnName = 
templateColumns[i].getIdentifier();
-                               if (!table.containsColumn(columnName)) {
+                    if (!table.containsColumn(columnName)) {
                         throw new UserException(_loc.get(
                                 "unique-missing-column",
                                 new Object[]{cm, columnName, tableName,
                                 Arrays.toString(table.getColumnNames())}));
-                               }
+                    }
                     Column uniqueColumn = table.getColumn(columnName);
-                               uniqueColumns[i] = uniqueColumn;
-                       }
-                       Unique unique = createUnique(cm, "unique", template,
-                                       uniqueColumns, adapt);
-                       if (unique != null)
-                               result.add(unique);
-               }
+                    uniqueColumns[i] = uniqueColumn;
+                }
+                Unique unique = createUnique(cm, "unique", template,
+                        uniqueColumns, adapt);
+                if (unique != null)
+                    result.add(unique);
+            }
         }
         return result.toArray(new Unique[result.size()]);
     }
 
+    /**
+     * Get all indices associated with both the primary and/or
+     * secondary tables.
+     *
+     */
+    public Index[] getIndices(MetaDataContext cm, boolean adapt) {
+        if (_indices.isEmpty())
+            return new Index[0];
+        List<Index> result = new ArrayList<>();
+        for (DBIdentifier tableName : _indices.keySet()) {
+            List<Index> indices = _indices.get(tableName);
+            for (Index template : indices) {
+                Column[] templateColumns = template.getColumns();
+                Column[] columns = new Column[templateColumns.length];
+                Table table = getTable((ClassMapping)cm, tableName, adapt);
+                for (int i = 0; i < columns.length; i++) {
+                    DBIdentifier columnName = 
templateColumns[i].getIdentifier();
+                    if (!table.containsColumn(columnName)) {
+                        throw new UserException(_loc.get(
+                                "index-missing-column",
+                                new Object[]{cm, columnName, tableName,
+                                Arrays.toString(table.getColumnNames())}));
+                    }
+                    Column column = table.getColumn(columnName);
+                    columns[i] = column;
+                }
+                Index idx = createIndex(cm, "index", template, columns, adapt);
+                if (idx != null)
+                    result.add(idx);
+            }
+        }
+        return result.toArray(new Index[result.size()]);
+    }
+
     @Override
     public File getSourceFile() {
         return _file;
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 36079b2..f267615 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
@@ -416,6 +416,11 @@ unique-missing-column: The column "{1}" in a unique 
constraint in "{0}" on \
 unique-no-table: A unique constraint on table "{0}" can not be added to \
        mapping of class "{1}" because the table does neither match its primary 
\
        table "{2}" nor any of its secondary table(s) "{3}".
+index-no-table: Index on table "{0}" can not be added to \
+       mapping of class "{1}" because the table does neither match its primary 
\
+       table "{2}" nor any of its secondary table(s) "{3}".
+index-missing-column: The column "{1}" in a index in "{0}" on \
+       table "{2}" can not be found in the list of available columns "{3}".
 bad-version-column-table: One of the version column "{0}" has been associated \
        with table "{1}", but no primary or secondary table of such name exists.
 version-type-unsupported: Version field "{0}" of {1} is not supported.
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 592328a..d22431b 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
@@ -615,6 +615,7 @@ public class AnnotationPersistenceMappingParser
         }
         addUniqueConstraints(tName.getName(), cm, cm.getMappingInfo(),
             table.uniqueConstraints());
+        addIndices(tName.getName(), cm, cm.getMappingInfo(), table.indexes());
     }
 
     Unique createUniqueConstraint(MetaDataContext ctx, UniqueConstraint anno) {
@@ -643,7 +644,7 @@ public class AnnotationPersistenceMappingParser
             Unique unique = createUniqueConstraint(ctx, anno);
             unique.setTableIdentifier(DBIdentifier.newTable(table, delimit()));
             if (info instanceof ClassMappingInfo)
-                ((ClassMappingInfo) info).addUnique(table, unique);
+                ((ClassMappingInfo) 
info).addUnique(DBIdentifier.newTable(table), unique);
             else if (info instanceof FieldMappingInfo)
                 ((FieldMappingInfo) info).addJoinTableUnique(unique);
             else
@@ -651,6 +652,40 @@ public class AnnotationPersistenceMappingParser
         }
     }
 
+
+    org.apache.openjpa.jdbc.schema.Index createIndex(MetaDataContext ctx, 
javax.persistence.Index anno) {
+        String columnNames = anno.columnList();
+        if (StringUtil.isEmpty(columnNames))
+            throw new UserException(_loc.get("index-no-column", ctx));
+        DBIdentifier[] sColNames = 
DBIdentifier.toArray(columnNames.split(","), DBIdentifierType.COLUMN, 
delimit());
+        org.apache.openjpa.jdbc.schema.Index indx = new 
org.apache.openjpa.jdbc.schema.Index();
+        for (int i = 0; i < sColNames.length; i++) {
+            if (DBIdentifier.isEmpty(sColNames[i]))
+                throw new UserException(_loc.get("index-empty-column",
+                        Arrays.toString(sColNames), ctx));
+            Column column = new Column();
+            column.setIdentifier(sColNames[i]);
+            indx.addColumn(column);
+        }
+        indx.setUnique(anno.unique());
+        if (!StringUtil.isEmpty(anno.name())) {
+            indx.setIdentifier(DBIdentifier.newConstraint(anno.name(), 
delimit()));
+        }
+        return indx;
+    }
+
+    void addIndices(String table, MetaDataContext ctx,
+        MappingInfo info, javax.persistence.Index... indices) {
+        for (javax.persistence.Index anno : indices) {
+            org.apache.openjpa.jdbc.schema.Index idx = createIndex(ctx, anno);
+            idx.setTableIdentifier(DBIdentifier.newTable(table, delimit()));
+            if (info instanceof ClassMappingInfo)
+                ((ClassMappingInfo) 
info).addIndex(DBIdentifier.newTable(table), idx);
+            else
+                throw new InternalException();
+        }
+    }
+
     /**
      * Form a qualified table name from a schema and table name.
      */
@@ -1644,7 +1679,7 @@ public class AnnotationPersistenceMappingParser
 
         // cache the JAXB XmlRootElement class if it is present so we do not
         // have a hard-wired dependency on JAXB here
-        Class xmlRootElementClass = null;
+        Class<?> xmlRootElementClass = null;
         try {
             xmlRootElementClass = 
Class.forName("javax.xml.bind.annotation.XmlRootElement");
         } catch (Exception e) {
@@ -1669,7 +1704,7 @@ public class AnnotationPersistenceMappingParser
                     .getDBDictionary();
                 if (dict.supportsXMLColumn)
                     // column maps to xml type
-                    ((Column) 
cols.get(i)).setTypeIdentifier(DBIdentifier.newColumnDefinition(dict.xmlTypeName));
+                    
cols.get(i).setTypeIdentifier(DBIdentifier.newColumnDefinition(dict.xmlTypeName));
             }
 
             unique |= (pcols[i].unique()) ? TRUE : FALSE;
diff --git 
a/openjpa-persistence-jdbc/src/main/resources/org/apache/openjpa/persistence/jdbc/localizer.properties
 
b/openjpa-persistence-jdbc/src/main/resources/org/apache/openjpa/persistence/jdbc/localizer.properties
index f31c6de..b4ab97c 100644
--- 
a/openjpa-persistence-jdbc/src/main/resources/org/apache/openjpa/persistence/jdbc/localizer.properties
+++ 
b/openjpa-persistence-jdbc/src/main/resources/org/apache/openjpa/persistence/jdbc/localizer.properties
@@ -53,6 +53,10 @@ unique-empty-column: A unique constraint "{0}" specified in 
mapping of class  \
 unique-many-on-seq-unsupported: More than one unique constraints is specified \
        on sequence generator "{1}" in "{0}". But multiple unique constraint on 
\
        sequence generator is currently not supported.
+index-no-column: An index specified in mapping of "{0}" specified \
+    no column.
+index-empty-column: An index "{0}" specified in mapping of class  \
+    "{1}" includes an empty column.
 discriminator-on-abstract-class: A discriminator value has been specified for \
        the abstract class "{0}". The discriminator will never be used and may 
be \
        safely removed.
diff --git 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/EntityWithIndices.java
 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/EntityWithIndices.java
new file mode 100644
index 0000000..cc073d1
--- /dev/null
+++ 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/EntityWithIndices.java
@@ -0,0 +1,76 @@
+/*
+ * 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.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Index;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "INDICES1"
+       , indexes = {@Index(name = "idx_index1", columnList = "index1")
+               , @Index(name = "idx_long", columnList = "LONG_NAME", unique = 
true)})
+public class EntityWithIndices {
+       @Id
+       @Column(name = "PK")
+       private Long pk;
+
+       @Column(name = "INDEX1")
+       private String index1;
+
+       @Column(name = "LONG_NAME")
+       private String longName;
+
+       @Column(name = "NAME")
+       private String name;
+
+       public Long getPk() {
+               return pk;
+       }
+
+       public void setPk(Long pk) {
+               this.pk = pk;
+       }
+
+       public String getIndex1() {
+               return index1;
+       }
+
+       public void setIndex1(String index1) {
+               this.index1 = index1;
+       }
+
+       public String getLongName() {
+               return longName;
+       }
+
+       public void setLongName(String longName) {
+               this.longName = longName;
+       }
+
+       public String getName() {
+               return name;
+       }
+
+       public void setName(String name) {
+               this.name = name;
+       }
+}
diff --git 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestIndices.java
 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestIndices.java
new file mode 100644
index 0000000..f105d64
--- /dev/null
+++ 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestIndices.java
@@ -0,0 +1,64 @@
+/*
+ * 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.util.HashSet;
+import java.util.Set;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.identifier.DBIdentifier;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+import org.junit.Test;
+
+public class TestIndices extends SingleEMFTestCase {
+       @Override
+       public void setUp() {
+               setUp(EntityWithIndices.class, CLEAR_TABLES
+//                     ,"openjpa.Log","SQL=trace"
+               );
+       }
+
+       @Test
+       public void testIndicesCreated() {
+               JDBCConfiguration conf = (JDBCConfiguration) 
emf.getConfiguration();
+               ClassMapping cls = 
conf.getMappingRepositoryInstance().getMapping(EntityWithIndices.class, null, 
true);
+               Table table = cls.getTable();
+               Index idx1 = 
table.getIndex(DBIdentifier.newIndex("idx_index1"));
+               assertNotNull("Defined index should exist", idx1);
+               assertFalse(idx1.isUnique());
+
+               Index idx2 = table.getIndex(DBIdentifier.newIndex("idx_long"));
+               assertNotNull("Defined index should exist", idx2);
+               assertTrue(idx2.isUnique());
+
+               Set<String> indexedCols = new HashSet<>();
+               for (Index idx : table.getIndexes()) {
+                       for (Column col : idx.getColumns()) {
+                               indexedCols.add(col.getIdentifier().getName());
+                       }
+               }
+               assertTrue(indexedCols.contains("INDEX1"));
+               assertTrue(indexedCols.contains("LONG_NAME"));
+               assertFalse(indexedCols.contains("NAME"));
+       }
+}

Reply via email to