Hibernate 5.x和Spring Data 2.x:如何在服务保存方法中更新原始对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate 5.x和Spring Data 2.x:如何在服务保存方法中更新原始对象相关的知识,希望对你有一定的参考价值。

我正在从以下位置升级Web应用程序:

Spring(MVC)4.2.9.RELEASE,Hibernate 4.3.8.Final和1.7.1.RELEASE

Spring(MVC)5.0.2.RELEASE,Hibernate 5.2.12.Final和Spring Data 2.0.2.RELEASE。

Web应用程序在Windows和MS SQL Server 2014 Enterprise上运行。

升级并没有强迫我更改Hibernate和JPA的设置。但是,现在程序的行为非常不同,这将在下面解释。

以下是应用程序中的典型服务方法,它保存一个新的Account对象,然后如果它是一个新对象则更新其值,然后返回它。 Account对象的ID字段定义如下:

@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;

这是服务方法:

@Override
@Transactional
public Account saveAccount(Account acc) {

    //Step 1
    //save method from Spring Data
    accountRepository.save(acc); 

    //stringId is set manually only once and it is set only when a new accout object is created
    if (acc.getStringId() == null) { 

        //Step 2
        acc.setStringId("some_string_id");
    }

    return acc;
}

以下是升级之前的行为:

第1步:acc是保存后的同一个对象。保存后,其id字段从null更新为Long值。

第2步:新值自动序列化为数据库。请注意,save方法没有显式数据库调用。

以下是升级后的行为:

第1步:使用accountRepository.save(acc)不会更新acc对象。要获取具有新id的对象,我必须按以下方式执行:

acc = accountRepository.save(acc)

第2步:不为新对象保存字符串ID。

我正在寻找方法使系统在升级之前正常工作。原因是应用程序并不简单,我在应用程序中遵循了编程模式(好的或坏的)。我想避免很多变化和重新测试。

这是相关配置

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.2.xsd
          http://www.springframework.org/schema/data/jpa    
          http://www.springframework.org/schema/data/jpa/spring-jpa-1.1.xsd                              
          http://www.springframework.org/schema/tx
          http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
          http://www.springframework.org/schema/jdbc 
          http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">

    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <constructor-arg ref="hikariConfig" />
    </bean> 

    <bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
        <property name="poolName" value="derek6HikariCP" />
        <property name="connectionTestQuery" value="${jdbc.connectionTestQuery}" />
        <property name="dataSourceClassName" value="${jdbc.dataSourceClassName}" />
        <property name="maximumPoolSize" value="${jdbc.maximumPoolSize}" />
        <property name="minimumIdle" value="${jdbc.minimumIdle}" />
        <property name="idleTimeout" value="${jdbc.idleTimeout}" />
        <property name="connectionTimeout" value="${jdbc.connectionTimeout}" />
        <property name="dataSourceProperties">
            <props>
                <prop key="url">${jdbc.url}</prop>
                <prop key="user">${jdbc.username}</prop>
                <prop key="password">${jdbc.password}</prop>
            </props>
        </property>     
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="dataSource"/>
    </bean>

    <bean  id="entityManagerFactory" name="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="packagesToScan" value="myproject.entity" />
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>                                 
                <prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
                <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
            </props>
        </property>
    </bean>     

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="emf" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>   

    <context:annotation-config />  

    <jpa:repositories base-package="myproject.entity"
        entity-manager-factory-ref="emf" transaction-manager-ref="transactionManager" />  

</beans>
答案

我想这是由于冲洗策略。你应该看看:https://vladmihalcea.com/how-does-the-auto-flush-work-in-jpa-and-hibernate/。要更好地理解。

在这两个版本更改之间,可能会发生他们已更改其刷新策略默认值。所以首先阅读上面的文档并根据需要配置代码。

以上是关于Hibernate 5.x和Spring Data 2.x:如何在服务保存方法中更新原始对象的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA 和 Hibernate

Spring Data JDBC / Spring Data JPA 与 Hibernate

Spring + Hibernate 审计(无 Spring Data)

spring-data-jpa+hibernate 各种缓存的配置演示

Hibernate 命名查询和 Spring Data SQL 注入

使用 Spring Boot 和 Spring Data JPA 的 Hibernate 拦截器或侦听器