2011-03-21 5 views
2

Spring (3.0.5), Hibernate (3.6.0) 및 Wicket (1.4.14)를 사용하여 응용 프로그램을 개발하는 동안 이상한 문제가 발생했습니다. 문제는 : 내가 데이터베이스에 개체를 저장하거나 수정할 수 없다는 것입니다. EntityManager.persist (foo)에 대한 객체 또는 호출의 모든 변경 사항이 단순히 무시된다는 것을 의미하지는 않습니다. 작업을 선택합니다. 여기 Spring 내에서 트랜잭션이 시작되지 않음 @ Transaction_transactional 메서드

public class ComicDetailsPage extends PublicBasePage { 

@Override 
protected void onConfigure() { 
    System.out.println("In onConfigure"); 
    super.onConfigure(); 
    comicDAO.insert("abc"); 

} 

@SpringBean(name="comicDAO") 
private ComicDAO comicDAO; 

    (....) 

내가 로깅을 설정 comicDAO

@Service 
public class ComicDAO { 

@PersistenceContext 
private EntityManager em; 

(...) 

@Transactional 
public void insert(String title) { 
    Comic c = new Comic(); 
    c.setTitle(title); 
    em.persist(c); 
} 

@Transactional 
public Comic add1toTitle(int pk) { 
    System.out.println("Beginning fetching"); 
    Comic c = em.find(Comic.class, pk); 
    System.out.println("Fetched updating"); 
    c.setTitle(c.getTitle()+"1"); 
    System.out.println("Updated persisting"); 
    em.persist(c); 
    System.out.println("Persisted returning"); 
    return c; 
} 

이며, 여기의 관련 부분은 다음과 같은, 내가 데이터베이스에 객체를 저장하려고 일부 개찰구 페이지에 -

샘플의 경우는 간단하다 로그 (Hibernate와 Spring 모두 TRACE로 설정 됨). 나는 ** 중요한 라인이라고 생각하는 라인에 **를 추가했다.

In onConfigure 
01:53:19.330 [qtp2119047503-15] DEBUG o.s.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'txManager' 
**01:53:19.330 [qtp2119047503-15] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13006687993** 
**01:53:19.330 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - begin** 
01:53:19.330 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection 
01:53:19.335 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - current autocommit status: true 
01:53:19.335 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - disabling autocommit 
01:53:19.336 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - after transaction begin 
01:53:19.336 [qtp2119047503-15] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13006687993 
01:53:19.336 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - setting flush mode to: AUTO 
01:53:19.336 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - setting cache mode to: NORMAL 
01:53:19.337 [qtp2119047503-15] TRACE org.hibernate.engine.IdentifierValue - id unsaved-value: 0 
01:53:19.337 [qtp2119047503-15] TRACE org.hibernate.event.def.AbstractSaveEventListener - transient instance of: pl.m4ks.comics.entity.Comic 
01:53:19.337 [qtp2119047503-15] TRACE org.hibernate.event.def.DefaultPersistEventListener - saving transient instance 
**01:53:19.338 [qtp2119047503-15] TRACE org.hibernate.event.def.AbstractSaveEventListener - saving [pl.m4ks.comics.entity.Comic#<null>]** 
**01:53:19.341 [qtp2119047503-15] DEBUG org.hibernate.event.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress** 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - closing session 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.jdbc.ConnectionManager - connection already null in cleanup : no action 
01:53:19.341 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - commit 
**01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - automatically flushing session** 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - before transaction completion 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - before transaction completion 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - re-enabling autocommit 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - committed JDBC Connection 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - after transaction completion 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - after transaction completion 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - closing session 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.jdbc.ConnectionManager - performing cleanup 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - after transaction completion 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - after transaction completion 

물론 개체가 데이터베이스에 저장되지 않습니다.

마지막 파일 - 내 applicationCOntext.xml 나는이 문제와 그 해결 방법이 될 수 있는지 아무 생각

<?xml version="1.0" encoding="UTF-8"?> 
<beans (...)> 

    <context:component-scan base-package="pl.m4ks.comics"/> 
    <context:annotation-config /> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> 
     <property name="driverClass" value="com.mysql.jdbc.Driver"/> 
     <property name="url" value="jdbc:mysql://localhost:8889/comics" /> 
     <property name="username" value="root"/> 
     <property name="password" value="root" />   
    </bean> 

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

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource"> 
      <ref bean="dataSource"/> 
     </property> 
     <property name="packagesToScan"> 
      <value>pl.m4ks.comics</value> 
     </property> 
    </bean> 


    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory" /> 
     </property> 
    </bean> 

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

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

. 내 코드에서 트랜잭션을 관리하고 싶지 않습니다. 이것이 Spring의 목적입니다.

+0

wicket 클래스 (시스템 .getClass())의 dao의 실제 유형은 무엇입니까? 그리고 DAO는 어떤 생성자를 가지고 있습니까? – Bozho

+0

wicket 태그가이 질문과 관련이 없으므로 제거되었습니다 (문제는 개찰 코드에 포함되지 않음). Java 및 JPA 태그가 추가되었습니다. –

답변

13

a) 귀하가 정의하는 모두 최대 절전 모드 SessionFactory와 JPA EntitymanagerFactory. 어느 쪽이 될 것인가? Hibernate의 Session API 또는 JPA의 Entitymanager API를 Hibernate와 함께 제공 업체로 사용하십시오. 둘 다 사용할 수는 없습니다.

b) 귀하가 HibernateTransactionManager를 정의하지만, 당신은 당신의 코드에서 EntityManager를 사용하고 있기 때문에, 당신은 JpaTransactionManager 대신 필요

<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="myEmf"/> 
</bean 
여기

이 applicationContext.xml의 주석 버전입니다 :

<?xml version="1.0" encoding="UTF-8"?> 
<beans (...)> 

    <context:component-scan base-package="pl.m4ks.comics"/> 
    <context:annotation-config /> 

    <bean id="dataSource" 
    class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> 
     <property name="driverClass" value="com.mysql.jdbc.Driver"/> 
     <property name="url" value="jdbc:mysql://localhost:8889/comics" /> 
     <property name="username" value="root"/> 
     <property name="password" value="root" />   
    </bean> 

    <!-- use either this: --> 
    <bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="main" /> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <!-- or this --> 
    <bean id="sessionFactory" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource"> 
      <ref bean="dataSource"/> 
     </property> 
     <property name="packagesToScan"> 
      <value>pl.m4ks.comics</value> 
     </property> 
    </bean> 
    <!-- (but not both) --> 

    <!-- this is correct for AnnotationSessionFactoryBean, but not if you use 
     LocalContainerEntityManagerFactoryBean --> 
    <bean id="txManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory" /> 
     </property> 
    </bean> 

    <!-- not necessary, <context:annotation-config /> automatically includes this --> 
    <bean 
    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

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

디자인 노트 : DAO는 트랜잭션이 아니어야합니다.. 트랜잭션을 관리하는 서비스 계층을 사용해야합니다. 참조 용으로 this question (및 기타 다수 참조)을 참조하십시오.

+0

답변을 주셔서 대단히 감사합니다. applicationCOntext를 편집하려고했습니다.xml - 난 그냥 entityManagerFactory 콩 주석. 이제 얻을 것입니다 'org.springframework.beans.factory.NoSuchBeanDefinitionException : [javax.persistence.EntityManagerFactory] 유형의 고유 한 bean이 정의되지 않았습니다 : 예상 된 단일 bean이지만 찾았습니다.'DAO에서 entityManager를 사용하려고 시도 했으므로 0'입니다. – M4ks

+0

@ M4ks 그렇다면 EntityManagerFactory가 아닌 SessionFactory를 주석으로 처리해야합니다. –

+0

그렇게 생각합니다. 하지만 entityManager없이 데이터베이스 작업을 수행하려면 어떻게해야합니까? – M4ks

-3

당신은 실제 데이터베이스에 저장하려면 flush()

EntityManager의

에 다음과 같은 메소드를 호출 할 필요가

+2

올바르지 않습니다. Spring TransactionManager가 올바르게 설정되면 entityManager.flush()가 자동으로 호출됩니다. –

0

최대 절전 모드 설정에서 hibernate.connection.autocommit = true로 설정해 보셨습니까? 그것은 문제를 해결할 것입니다. 그러나 접근 방법이 얼마나 효율적인지 알아 내야합니다.

관련 문제