在em.MERGE JPA之后更新ROLLEDBACK

时间:2014-07-27 00:14:20

标签: java spring hibernate jpa transactions

嗨,大家好。当我尝试合并我的实体时,我遇到了问题。 我用新字段解析对象实体" Name"来自休息服务的put请求。 我试图将实体与新的"名称"字段到我的数据库,但我在更新操作后得到回滚,也许你知道为什么? 这是我的控制器

@RequestMapping(value = "/updDep", method = RequestMethod.PUT)
      @ResponseBody
      public String updDeps(@RequestBody Department department ) {
        departmentService.addDepartment(department);
        System.out.println("after merge;  in controller");
        return "Success";
    }

使用addDepartment()方法的Department Service类:

@Repository
public class DepartmentServiceImpl implements  DepartmentService {

    @PersistenceContext(unitName = "MyPersistenceUnit")
    private EntityManager entityManager;
....
//getter/setter entityManager....
...
@Override
@Transactional
public void updDepartment(Department department) {
    Department department1 = findById(department.getId());
    department1.setName(department.getName());
    /*  NOT WORKS TOO, STILL ROOLBAKED!
    Department managedDep =  getEntityManager().merge(department);   
    managedDep.setName(department.getName());
    */
}

项目结构: enter image description here

的persistence.xml

 <persistence-unit name="MyPersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/testbd"/>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.username" value="root"/>
            <property name="hibernate.connection.password" value="root"/>
            <!--<property name="hibernate.hbm2ddl.import_files" value= "import.sql"/>-->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
        </properties>
    </persistence-unit>

</persistence>

SPRING CONFIG

 <mvc:annotation-driven />

    <context:annotation-config />
    <context:component-scan base-package="epam.rest" />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>classpath:jdbc.properties</value>
        </property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />

    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
         <property name="persistenceUnitName" value="MyPersistenceUnit"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="dataSource" ref="dataSource" />
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
</beans>

LOG4J日志:

11:55:42,672 TRACE DefaultFlushEntityEventListener:281 - Updating entity: [epam.rest.entity.Department#1]
11:55:42,681 DEBUG Collections:190 - Collection found: [epam.rest.entity.Department.worker#1], was: [epam.rest.entity.Department.worker#1] (initialized)
11:55:42,682 TRACE AbstractFlushingEventListener:242 - Processing unreferenced collections
11:55:42,682 TRACE AbstractFlushingEventListener:254 - Scheduling collection removes/(re)creates/updates
11:55:42,682 DEBUG AbstractFlushingEventListener:118 - Flushed: 0 insertions, 1 updates, 0 deletions to 4 objects
11:55:42,683 DEBUG AbstractFlushingEventListener:125 - Flushed: 0 (re)creations, 0 updates, 0 removals to 1 collections
11:55:42,683 DEBUG EntityPrinter:114 - Listing entities:
11:55:42,684 DEBUG EntityPrinter:121 - epam.rest.entity.Worker{id=2, department=epam.rest.entity.Department#1, salary=1200, fio=Kozlovich Andrei Vicktorovich}
11:55:42,684 DEBUG EntityPrinter:121 - epam.rest.entity.Worker{id=1, department=epam.rest.entity.Department#1, salary=1000, fio=Gabriel Alexei Nicolaevich}
11:55:42,684 DEBUG EntityPrinter:121 - epam.rest.entity.Worker{id=3, department=epam.rest.entity.Department#1, salary=1500, fio=Baym Alena Nicolaevna}
11:55:42,686 DEBUG EntityPrinter:121 - epam.rest.entity.Department{id=1, name=IT123, worker=[epam.rest.entity.Worker#2, epam.rest.entity.Worker#3, epam.rest.entity.Worker#1]}
11:55:42,687 TRACE AbstractFlushingEventListener:327 - Executing flush
11:55:42,697 TRACE AbstractEntityPersister:3166 - Updating entity: [epam.rest.entity.Department#1]
11:55:42,698 TRACE AbstractServiceRegistryImpl:146 - Initializing service [role=org.hibernate.engine.jdbc.batch.spi.BatchBuilder]
11:55:42,704 TRACE AbstractServiceRegistryImpl:146 - Initializing service [role=org.hibernate.service.jmx.spi.JmxService]
11:55:42,706 TRACE BatchBuilderImpl:68 - Building batch [size=1]
11:55:42,708 DEBUG SQL:104 - 
    update
        departments 
    set
        name=? 
    where
        id=?
11:55:42,710 TRACE JdbcCoordinatorImpl:319 - Registering statement [com.mysql.jdbc.JDBC4PreparedStatement@646b0e6a: update departments set name=** NOT SPECIFIED ** where id=** NOT SPECIFIED **]
11:55:42,710 TRACE AbstractEntityPersister:2780 - Dehydrating entity: [epam.rest.entity.Department#1]
11:55:42,712 TRACE BasicBinder:84 - binding parameter [1] as [VARCHAR] - IT123
11:55:42,713 TRACE BasicBinder:84 - binding parameter [2] as [BIGINT] - 1
11:55:42,714 TRACE JdbcCoordinatorImpl:358 - Releasing statement [com.mysql.jdbc.JDBC4PreparedStatement@646b0e6a: update departments set name='IT123' where id=1]
11:55:42,715 TRACE JdbcCoordinatorImpl:476 - Closing prepared statement [com.mysql.jdbc.JDBC4PreparedStatement@646b0e6a: update departments set name='IT123' where id=1]
11:55:42,715 TRACE JdbcCoordinatorImpl:249 - Starting after statement execution processing [ON_CLOSE]
11:55:42,717 TRACE JdbcCoordinatorImpl:249 - Starting after statement execution processing [ON_CLOSE]
11:55:42,718 DEBUG AbstractTransactionImpl:203 - rolling back
11:55:42,786 DEBUG JdbcTransaction:164 - rolled JDBC Connection
11:55:42,787 DEBUG JdbcTransaction:126 - re-enabling autocommit
11:55:42,788 TRACE TransactionCoordinatorImpl:136 - after transaction completion
11:55:42,792 TRACE SessionImpl:624 - after transaction completion
11:55:42,794 TRACE SessionImpl:342 - Closing session
11:55:42,795 TRACE JdbcCoordinatorImpl:171 - Closing JDBC container [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl@6583023d]
11:55:42,796 DEBUG JdbcCoordinatorImpl:173 - HHH000420: Closing un-released batch
11:55:42,797 TRACE LogicalConnectionImpl:164 - Closing logical connection
11:55:42,797 DEBUG LogicalConnectionImpl:232 - Releasing JDBC connection
11:55:42,798 TRACE DriverManagerConnectionProviderImpl:233 - Returning connection to pool, pool size: 1
11:55:42,799 DEBUG LogicalConnectionImpl:250 - Released JDBC connection
11:55:42,799 TRACE LogicalConnectionImpl:176 - Logical connection closed

工人实体

@Entity
@Table(name = "workers")
public class Worker {

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

    @Column(nullable = false)
    private String fio;

    @ManyToOne(cascade =  {CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
    private Department department;

    @Column(nullable = false)
    private Integer salary;
......

部门实体

@Entity
@Table(name ="departments")
public class Department implements Serializable {

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

    @Column(nullable = false)
    private String name;

    @OneToMany(cascade =  {CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER, mappedBy = "department")
    private Set<Worker> worker;
.......

告诉我我错的是什么?!

更新1 我更新了我的代码 1)删除persistence.xml 2)在服务中删除(unitName =&#34; MyPersistenceUnit&#34;):

 @PersistenceContext
 private EntityManager entityManager;

2)编辑despatcher-servlet.xml: 现在它看起来像那样:

<mvc:annotation-driven />
    <context:component-scan base-package="epam.rest" />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>classpath:jdbc.properties</value>
        </property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />

    </bean>


    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="epam.rest.entity" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>

            </props>
        </property>
    </bean>


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

    </bean>

    <bean id="persistenceExceptionTranslationPostProcessor"
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
</beans>

但是当我尝试更新时,我仍然有相同的ROLLEDBACK

04:14:06,765 TRACE AbstractEntityPersister:3166 - Updating entity: [epam.rest.entity.Department#1]
04:14:06,766 TRACE AbstractServiceRegistryImpl:146 - Initializing service [role=org.hibernate.engine.jdbc.batch.spi.BatchBuilder]
04:14:06,772 TRACE AbstractServiceRegistryImpl:146 - Initializing service [role=org.hibernate.service.jmx.spi.JmxService]
04:14:06,774 TRACE BatchBuilderImpl:68 - Building batch [size=1]
04:14:06,776 DEBUG SQL:104 - update departments set name=? where id=?
04:14:06,777 TRACE JdbcCoordinatorImpl:319 - Registering statement [com.mysql.jdbc.JDBC4PreparedStatement@3918a7aa: update departments set name=** NOT SPECIFIED ** where id=** NOT SPECIFIED **]
04:14:06,778 TRACE AbstractEntityPersister:2780 - Dehydrating entity: [epam.rest.entity.Department#1]
04:14:06,779 TRACE BasicBinder:84 - binding parameter [1] as [VARCHAR] - IT21
04:14:06,780 TRACE BasicBinder:84 - binding parameter [2] as [BIGINT] - 1
04:14:06,782 TRACE JdbcCoordinatorImpl:358 - Releasing statement [com.mysql.jdbc.JDBC4PreparedStatement@3918a7aa: update departments set name='IT21' where id=1]
04:14:06,783 TRACE JdbcCoordinatorImpl:476 - Closing prepared statement [com.mysql.jdbc.JDBC4PreparedStatement@3918a7aa: update departments set name='IT21' where id=1]
04:14:06,783 TRACE JdbcCoordinatorImpl:249 - Starting after statement execution processing [ON_CLOSE]
04:14:06,785 TRACE JdbcCoordinatorImpl:249 - Starting after statement execution processing [ON_CLOSE]
04:14:06,785 DEBUG AbstractTransactionImpl:203 - rolling back
04:14:06,856 DEBUG JdbcTransaction:164 - rolled JDBC Connection
04:14:06,857 DEBUG JdbcTransaction:126 - re-enabling autocommit
04:14:06,858 TRACE TransactionCoordinatorImpl:136 - after transaction completion
04:14:06,862 TRACE SessionImpl:624 - after transaction completion
04:14:06,866 TRACE SessionImpl:342 - Closing session
04:14:06,867 TRACE JdbcCoordinatorImpl:171 - Closing JDBC container [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl@71799400]
04:14:06,867 DEBUG JdbcCoordinatorImpl:173 - HHH000420: Closing un-released batch
04:14:06,868 TRACE LogicalConnectionImpl:164 - Closing logical connection
04:14:06,868 DEBUG LogicalConnectionImpl:232 - Releasing JDBC connection
04:14:06,868 DEBUG LogicalConnectionImpl:250 - Released JDBC connection
04:14:06,869 TRACE LogicalConnectionImpl:176 - Logical connection closed

现在有什么问题?! 的 UPDATE2 我查看了我的pom.xml文件:

....
   <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.1.8.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.1.8.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
        </dependency>
.....

所以当我删除时:

 <dependency>
                <groupId>org.hibernate.javax.persistence</groupId>
                <artifactId>hibernate-jpa-2.0-api</artifactId>
                <version>1.0.1.Final</version>
            </dependency>

一切正常!

1 个答案:

答案 0 :(得分:1)

问题是你为Hibernate提供了两个不同的jdbc连接信息:

  1. 通过Spring配置的DataSourcw
  2. 通过Hibernate jdbc连接属性
  3. 因为您需要将Spring Transaction demarcation集成到Hibernate事务逻辑中,所以您只能依赖于您提供给JPA TransactionManager的DataSource。

    这也是您看到自动提交重新启用日志的原因。

    所以删除所有hibernate.connection。*行,你应该没问题:

    <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/testbd"/>
    <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
    <property name="hibernate.connection.username" value="root"/>
    <property name="hibernate.connection.password" value="root"/>
    

    删除这些行后,Hibernate不会使用自己的内部JDBC连接提供程序覆盖DataSource。