Spring Boot JPA - 将ID字段转换为大写的EntityManager

时间:2015-01-27 15:05:31

标签: hibernate jpa spring-data spring-boot spring-data-jpa

我正在构建一个Spring Boot应用程序,它根据以下属性自动配置我的JPA数据源。

spring.datasource.url=jdbc:jtds:sqlserver://localhost;DatabaseName=testDB;useCursors=true
spring.datasource.username=testDBUser
spring.datasource.password=test123
spring.datasource.driver-class-name=net.sourceforge.jtds.jdbc.Driver
spring.datasource.maxActive=100
spring.datasource.minIdle=5
spring.datasource.removeAbandoned=true
spring.datasource.removeAbandonedTimeout=300
spring.datasource.defaultTransactionIsolation=REPEATABLE_READ
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect
spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true  

现在,我有一个表格如下

TableA{
String id;
String prop1;
String prop2;
String prop3;
}

失败的测试用例如下。正如您在下面看到的,我只是想比较EntityManager与Spring Data Repository的结果。

测试失败,因为从EntityManager返回的“id”值是“D97”(大写),而从Spring Data存储库返回的值是“d97”。实际值是“d97”。

@Test
public void testIfSpringRepositoryWorks() {
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    List<TableAEntity> result = entityManager.createQuery("FROM TableAEntity WHERE id='d97'" , TableAEntity.class).getResultList();

    if(result==null) {
        Assert.fail("Empty Result from EntityManager for id: d97 ");
    } else {
        TableAEntity fromEntityManager = result.get(0);
        TableAEntity fromSpringJPA = tableARepository.findOne("d97");

        if(!fromEntityManager.equals(fromSpringJPA)) {
            Assert.fail("TableAEntity is not same");
        }
    }


    entityManager.getTransaction().commit();
    entityManager.close();
}

我不确定为什么EntityManager将我的id字段转换为大写字母。请帮助找出根本原因。

谢谢!

1 个答案:

答案 0 :(得分:1)

我不确定这是一个问题还是我创造一个解决方案的情况。但这是正在发生的事情。

在上面的测试中,我对Spring JPA的查询是

tableARepository.findOne("d97");

相当于

entityManager.find(TableA.class,"d97");

当执行两者中的任何一个时,代码的下面部分在Hibernate Row Reader逻辑中形成实体键(org.hibernate.loader.plan.exec.process.internal.RowSetProcessorHelper)。

public static EntityKey getOptionalObjectKey(QueryParameters queryParameters, SessionImplementor session) {
    final Object optionalObject = queryParameters.getOptionalObject();
    final Serializable optionalId = queryParameters.getOptionalId();
    final String optionalEntityName = queryParameters.getOptionalEntityName();

    return INSTANCE.interpretEntityKey( session, optionalEntityName, optionalId, optionalObject );
}

不用说,作为键传递的任何参数理想情况下都是返回对象的主键值(忽略数据库返回的值)。

现在,当我执行查询

 List<TableAEntity> result = entityManager.createQuery("FROM TableAEntity WHERE id='d97'" , TableAEntity.class).getResultList()

由于我没有直接将任何主键传递给hibernate,它可能只保留了hibernate返回的值。

现在,由于SQLServer默认排序规则不区分大小写,因此在返回数据时它会将我的主键大写。

我不确定为什么Hibernate会覆盖数据库返回的主键值的原因。

但是,如果hibernate具有关闭这种行处理逻辑的功能,那么它可能会有所帮助。

希望这有帮助!