Hibernate 5.x and Spring Data 2.x : how to make the original object updated in a service save method

谁说我不能喝 提交于 2019-12-25 00:39:21

问题


I am upgrading a web application from:

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

to

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

The web application runs on Windows and MS SQL Server 2014 Enterprise.

The upgrade did not force me to change the settings for Hibernate and JPA. However, now the program behaves very differently, which is explained below.

The following is a typcial service method in the application, which saves a new Account object, and then updates its value if it is a new object, then return it. The Account object has an ID field defined as follows:

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

This is the servie method:

@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;
}

Here is the behavior BEFORE the upgrade:

Step 1: acc is the same object after the save. Its id field is updated from null to a Long value after the save.

Step 2: The new value is automatically serialized to database. Note that there is no explicit database call to the save method.

Here is the behavior AFTER the upgrade:

Step 1: Using accountRepository.save(acc) only does not update the acc object. To get the object with new id, I have to do it the following way:

acc = accountRepository.save(acc)

Step 2: the string id is not saved for a new object.

I am looking for ways to make the system work the way before it was upgrade. The reason is that the application is not trivial, and I have followed the programming pattern (good or bad) throught the application. I would like to avoid lots of changes and re-tests.

Here is the related configuration

<?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>

回答1:


I guess that is due to the flush strategy. You should look into : https://vladmihalcea.com/how-does-the-auto-flush-work-in-jpa-and-hibernate/. to understand better.

Between this 2 version changes, it might happen that they have changed their flush strategy default. so first read the above document & configure your code as you want.



来源:https://stackoverflow.com/questions/47861929/hibernate-5-x-and-spring-data-2-x-how-to-make-the-original-object-updated-in-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!