使用EclipseLink自定义JPA字段名称映射

JBT*_*JBT 5 java jpa eclipselink java-ee

由于历史原因,我需要将当前项目中使用EclipseLink的驼峰分隔名称映射到下划线名称.我知道我们可以在JPA中单独定制名称映射,但是我们有一长串的驼峰名称要更改,所以我们希望尽可能避免使用那种样板代码.

我想要实现的目标如下.假设我们有一个实体类,如下所示:

@Entity
public class FooBar {
    @Id @GeneratedValue
    private Long id;

    @Temporal( TemporalType.TIMESTAMP )
    private Date dateCreated;
}
Run Code Online (Sandbox Code Playgroud)

我希望这个类映射到名为"foo_bar"和列"id"和"date_created"的表.请注意,数据库中的所有名称均为小写.

我用Google搜索,找到了更改表名的解决方案.但是,我无法弄清楚如何在实体类中更改字段名称.

下面是我的名字映射定制器,该方法updateFieldNameMappings()没有映射fieldNamefield_name,这是我想要实现的.问题归结为如何在类定义中获取字段名称.那么,我如何在EclipseLink中做到这一点?

public class JpaNameMappingCustomizer implements SessionCustomizer {

    @Override
    public void customize( Session session ) throws Exception {
        Map<Class, ClassDescriptor> descs = session.getDescriptors();
        Collection<ClassDescriptor> descriptors = descs.values();

        // This code assumes single table per descriptor!
        for (ClassDescriptor desc : descriptors) {
            updateTableNameMapping( desc );
            updateFieldNameMapping( desc );
        }
    }

    private void updateTableNameMapping ( ClassDescriptor desc ) {
        Class clazz = desc.getJavaClass();
        String tableName = camelCaseToUnderscore( clazz.getSimpleName() );
        desc.setTableName( tableName );
    }

    private void updateFieldNameMapping ( ClassDescriptor desc ) {
        // build name maps
        Field[] fields = desc.getJavaClass().getDeclaredFields();
        String tableName = desc.getTableName();
        Map<String,String> nameMap = new HashMap<>();
        String prefix = tableName + ".";
        for( Field field : fields ) {
            String name = field.getName();
            String key = prefix + name.toUpperCase();
            String value = prefix + camelCaseToUnderscore( name );
            nameMap.put( key, value );
        }

        for (DatabaseMapping mapping : desc.getMappings()) {
            if (mapping.isDirectToFieldMapping()) {
                DirectToFieldMapping directMapping = (DirectToFieldMapping) mapping;
                String oldFieldName = directMapping.getFieldName(); // format: table_name.FIELD
                directMapping.setFieldName( nameMap.get( oldFieldName ) );
            }
        }
    }

    private String camelCaseToUnderscore( String camelCase ) {
        return camelCase.trim().replaceAll("(?<!^)[A-Z](?!$)", "_$0").toLowerCase();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑11/10/13 我做了一些黑客攻击并更改了自定义程序.在updateFieldNameMapping()仍然没有做的伎俩.在我看来,该directMapping.setFieldName( nameMap.get( oldFieldName ) )方法中的这个语句实际上并没有改变字段名称映射,这真的让我感到困惑.

编辑11/11/13 我忘了说清楚我已经eclipselink.session.customizer启用了persistence.xml.也就是说,我在下面有一行persistence.xml:

<property name="eclipselink.session.customizer" value="pkg.JpaNameMappingCustomizer"/>
Run Code Online (Sandbox Code Playgroud)

pub*_*her 6

代替

directMapping.setFieldName(nameMap.get(oldFieldName ));
Run Code Online (Sandbox Code Playgroud)

尝试:

directMapping.getField().resetQualifiedName(nameMap.get(oldFieldName));
Run Code Online (Sandbox Code Playgroud)

这在EclipseLink 2.5.0下为我提供了诀窍