[SPRING] @Transactional 메서드에서 Spring 내에서 트랜잭션이 시작되지 않습니다.
SPRING@Transactional 메서드에서 Spring 내에서 트랜잭션이 시작되지 않습니다.
Spring (3.0.5), Hibernate (3.6.0) 및 Wicket (1.4.14)를 사용하여 응용 프로그램을 개발하는 동안 이상한 문제가 발생합니다. 문제는 : 내가 데이터베이스에 개체를 저장하거나 수정할 수 없다는 것입니다. EntityManager.persist (foo)에 대한 객체 또는 호출의 모든 변경 사항이 단순히 무시된다는 것을 의미하지 않습니다. 작업을 선택합니다.
예제 케이스는 간단합니다 - 일부 wicket 페이지에서 다음과 같이 데이터베이스에 객체를 저장하려고합니다.
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;
(....)
여기 코믹 DAO입니다
@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의 목적입니다.
해결법
-
==============================
1.a) 당신은 Hibernate SessionFactory와 JPA EntitymanagerFactory를 정의하고있다. 어느 쪽이 될 것인가? Hibernate의 Session API 또는 JPA의 Entitymanager API를 Hibernate와 함께 제공 업체로 사용하십시오. 둘 다 사용할 수는 없습니다.
a) 당신은 Hibernate 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는 트랜잭션이 아니어야합니다. 트랜잭션을 관리하는 서비스 계층을 사용해야합니다. 참조를 위해이 질문 및 많은 다른 사람을보십시오.
-
==============================
2.최대 절전 모드 설정에서 hibernate.connection.autocommit = true를 설정해 보셨습니까? 그러면 문제가 해결 될 것입니다. 그러나 접근 방법이 얼마나 효율적인지 알아 내야합니다.
최대 절전 모드 설정에서 hibernate.connection.autocommit = true를 설정해 보셨습니까? 그러면 문제가 해결 될 것입니다. 그러나 접근 방법이 얼마나 효율적인지 알아 내야합니다.
-
==============================
3.EntityManager에서 다음 메소드를 호출해야한다.
EntityManager에서 다음 메소드를 호출해야한다.
플러시()
데이터베이스에 실제 저장하려면
from https://stackoverflow.com/questions/5372859/no-transaction-starts-within-spring-transactional-method by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] ConcurentHashMap과 AtomicInteger를 스프링 서비스 클래스 내의 인스턴스 변수로 사용하기 (0) | 2019.04.29 |
---|---|
[SPRING] Jar의 여러 XML 파일을 사용하는 Spring ApplicationContext (0) | 2019.04.29 |
[SPRING] WebMvcConfigurerAdapter가 작동하지 않습니다. (0) | 2019.04.29 |
[SPRING] Spring 5와 JUnit 5 + Mockito - 컨트롤러 메소드는 null을 반환합니다. (0) | 2019.04.29 |
[SPRING] 스프링 보안 : configure (AuthenticationManagerBuilder auth) (0) | 2019.04.29 |