Customize JPA field name mapping using EclipseLink

后端 未结 4 1822
名媛妹妹
名媛妹妹 2021-01-12 16:01

I need to map camel-case names to underscore-separated names in my current project, which uses EclipseLink, due to historical reasons. I know we can customize name mapping i

相关标签:
4条回答
  • 2021-01-12 16:18

    In case you want to distinguish between non-annotated elements and annotated elements using @Column annotations, then I found a very beautiful example doing this:

    public class CamelCaseSessionCustomizer implements SessionCustomizer {
    
    @Override
    public void customize(Session session) throws SQLException {
        for (ClassDescriptor descriptor : session.getDescriptors().values()) {
            // Only change the table name for non-embedable entities with no
            // @Table already
            if (!descriptor.getTables().isEmpty() && descriptor.getAlias().equalsIgnoreCase(descriptor.getTableName())) {
                String tableName = addUnderscores(descriptor.getTableName());
                descriptor.setTableName(tableName);
                for (IndexDefinition index : descriptor.getTables().get(0).getIndexes()) {
                    index.setTargetTable(tableName);
                }
            }
            for (DatabaseMapping mapping : descriptor.getMappings()) {
                // Only change the column name for non-embedable entities with
                // no @Column already
    
                if (mapping instanceof AggregateObjectMapping) {
                    for (Association association : ((AggregateObjectMapping) mapping).getAggregateToSourceFieldAssociations()) {
                        DatabaseField field = (DatabaseField) association.getValue();
                        field.setName(addUnderscores(field.getName()));
    
                        for (DatabaseMapping attrMapping : session.getDescriptor(((AggregateObjectMapping) mapping).getReferenceClass()).getMappings()) {
                            if (attrMapping.getAttributeName().equalsIgnoreCase((String) association.getKey())) {
                                ((AggregateObjectMapping) mapping).addFieldTranslation(field, addUnderscores(attrMapping.getAttributeName()));
                                ((AggregateObjectMapping) mapping).getAggregateToSourceFields().remove(association.getKey());
                                break;
                            }
                        }
                    }
                } else if (mapping instanceof ObjectReferenceMapping) {
                    for (DatabaseField foreignKey : ((ObjectReferenceMapping) mapping).getForeignKeyFields()) {
                        foreignKey.setName(addUnderscores(foreignKey.getName()));
                    }
                } else if (mapping instanceof DirectMapMapping) {
                    for (DatabaseField referenceKey : ((DirectMapMapping) mapping).getReferenceKeyFields()) {
                        referenceKey.setName(addUnderscores(referenceKey.getName()));
                    }
                    for (DatabaseField sourceKey : ((DirectMapMapping) mapping).getSourceKeyFields()) {
                        sourceKey.setName(addUnderscores(sourceKey.getName()));
                    }
                } else {
                    DatabaseField field = mapping.getField();
                    if (field != null && !mapping.getAttributeName().isEmpty() && field.getName().equalsIgnoreCase(mapping.getAttributeName())) {
                        field.setName(addUnderscores(mapping.getAttributeName()));
                    }
                }
            }
        }
    }
    
    private static String addUnderscores(String name) {
        if (name.equalsIgnoreCase("begintime")) {
            System.err.println();
        }
        StringBuffer buf = new StringBuffer(name.replace('.', '_'));
        for (int i = 1; i < buf.length() - 1; i++) {
            if (Character.isLowerCase(buf.charAt(i - 1)) && Character.isUpperCase(buf.charAt(i)) && Character.isLowerCase(buf.charAt(i + 1))) {
                buf.insert(i++, '_');
            }
        }
        return buf.toString().toLowerCase();
    }
    
    }
    

    From https://gist.github.com/ganeshs/c0deb77ffae33dee4555

    0 讨论(0)
  • 2021-01-12 16:24

    Perhaps you could use my session customizer. It converts table names, and field names to Camel case. It supports inheritance and embeded entities. I tested for 2 years, and I got no issues or side effects. Enjoy it!

    import java.sql.SQLException;
    import java.util.Locale;
    import java.util.Vector;
    import org.eclipse.persistence.config.SessionCustomizer;
    import org.eclipse.persistence.descriptors.ClassDescriptor;
    import org.eclipse.persistence.internal.helper.DatabaseField;
    import org.eclipse.persistence.mappings.DatabaseMapping;
    import org.eclipse.persistence.sessions.Session;
    import org.eclipse.persistence.tools.schemaframework.IndexDefinition;
    
    public class CamelNamingStrategy implements SessionCustomizer {
        public static String unqualify(final String qualifiedName) {
            int loc = qualifiedName.lastIndexOf(".");
            return loc < 0 ? qualifiedName : qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1);
        }
    
        @Override
        public void customize(final Session session) throws SQLException {
            for (ClassDescriptor descriptor : session.getDescriptors().values()) {
                if (!descriptor.getTables().isEmpty()) {
                    // Take table name from @Table if exists
                    String tableName = null;
                    if (descriptor.getAlias().equalsIgnoreCase(descriptor.getTableName())) {
                        tableName = unqualify(descriptor.getJavaClassName());
                    } else {
                        tableName = descriptor.getTableName();
                    }
                    tableName = camelCaseToUnderscore(tableName);
                    descriptor.setTableName(tableName);
                    for (IndexDefinition index : descriptor.getTables().get(0).getIndexes()) {
                        index.setTargetTable(tableName);
                    }
                    Vector<DatabaseMapping> mappings = descriptor.getMappings();
                    camelCaseToUnderscore(mappings);
                } else if (descriptor.isAggregateDescriptor() || descriptor.isChildDescriptor()) {
                    camelCaseToUnderscore(descriptor.getMappings());
                }
            }
        }
    
        private void camelCaseToUnderscore(Vector<DatabaseMapping> mappings) {
            for (DatabaseMapping mapping : mappings) {
                DatabaseField field = mapping.getField();
                if (mapping.isDirectToFieldMapping() && !mapping.isPrimaryKeyMapping()) {
                    String attributeName = mapping.getAttributeName();
                    String underScoredFieldName = camelCaseToUnderscore(attributeName);
                    field.setName(underScoredFieldName);
                }
            }
        }
    
        private String camelCaseToUnderscore(final String name) {
            StringBuffer buf = new StringBuffer(name.replace('.', '_'));
            for (int i = 1; i < buf.length() - 1; i++) {
                if (Character.isLowerCase(buf.charAt(i - 1)) && Character.isUpperCase(buf.charAt(i))
                        && Character.isLowerCase(buf.charAt(i + 1))) {
                    buf.insert(i++, '_');
                }
            }
            return buf.toString().toLowerCase(Locale.ENGLISH);
        }
    }
    
    0 讨论(0)
  • 2021-01-12 16:26

    Instead of

    directMapping.setFieldName(nameMap.get(oldFieldName ));
    

    try:

    directMapping.getField().resetQualifiedName(nameMap.get(oldFieldName));
    

    This does the trick for me under EclipseLink 2.5.0

    0 讨论(0)
  • 2021-01-12 16:30

    I think you have missed adding following line in your persistence.xml to say EclipseLink to use your own SessionCustomizer

    <property name="eclipselink.session.customizer" value="your.company.package.name.JpaNameMappingCustomizer"/>
    

    Refer

    http://www.eclipse.org/eclipselink/documentation/2.5/dbws/creating_dbws_services002.htm

    http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_session_customizer.htm#CHDFBIEI

    0 讨论(0)
提交回复
热议问题