2014-09-30 2 views
4

내 응용 프로그램에서 spring 및 hibernate를 사용하고 있으며 Spring 트랜잭션을 사용하고 있습니다.spring @transactional을 사용하여 최대 절전 모드 session.flush

그래서 나는 메소드와 주석에 @transaction을 가진 서비스 레이어를 가지고 있고 DAO 레이어는 데이터베이스 쿼리를위한 메소드를 가지고있다. 나는 데이터베이스에 객체를 저장할 때

@Transactional(readOnly = false) 
public void get(){ 

} 

문제는 내가 DAO 계층 method.Why의 끝에서 session.flush()을 사용할 필요가있다?

나는 트랜잭션에 주석을 달았다면 스프링이 자동으로 서비스 메소드 완료시 트랜잭션을 커밋해야한다고 생각한다.

DAO 층 :

public BaseEntity saveEntity(BaseEntity entity) throws Exception { 
     try { 
      Session session = sessionFactory.getCurrentSession(); 
      session.saveOrUpdate(entity); 
      session.flush(); 
     } catch (HibernateException he) { 
      throw new Exception("Failed to save entity " + entity); 
     } 
     return entity; 
    } 

서비스 층 :

@Transactional(readOnly = false) 
    public BaseEntity saveEntity(BaseEntity entity) throws Exception { 
     return dao.saveEntity(entity); 
    } 

스프링 설정 : 당신이 당신의 DAO 방법에 대한 @Transactional이있는 경우

<context:property-placeholder properties-ref="deployProperties" /> 

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

    <!-- Activate Spring Data JPA repository support --> 
    <jpa:repositories base-package="com" /> 

    <!-- Declare a datasource that has pooling capabilities--> 
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
     destroy-method="close" 
     p:driverClass="${app.jdbc.driverClassName}" 
     p:jdbcUrl="${app.jdbc.url}" 
     p:user="${app.jdbc.username}" 
     p:password="${app.jdbc.password}" 
     p:acquireIncrement="5" 
     p:idleConnectionTestPeriod="60" 
     p:maxPoolSize="100" 
     p:maxStatements="50" 
     p:minPoolSize="10" /> 

    <!-- Declare a JPA entityManagerFactory --> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
     p:persistenceXmlLocation="classpath*:META-INF/persistence.xml" 
     p:persistenceUnitName="hibernatePersistenceUnit" 
     p:dataSource-ref="dataSource" 
     p:jpaVendorAdapter-ref="hibernateVendor"/> 

    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" 
     p:dataSource-ref="dataSource" p:configLocation="${hibernate.config}" 
     p:packagesToScan="com" /> 

    <!-- Specify our ORM vendor --> 
    <bean id="hibernateVendor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" 
       p:showSql="false"/> 

    <!-- Declare a transaction manager--> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
     p:entityManagerFactory-ref="entityManagerFactory"/> 
+1

봄은 당신을 위해 그것을하고'readonly = false'는 디폴트입니다. 당신은 그것을 선언하지 않았습니다 – Jaiwo99

+0

자동 커밋은'Session'을 DB로 즉시 플러시하지 않을 것이라고 생각합니다. 해당 트랜잭션에서 변경된 사항을 동일한 '세션'으로 작업하는 다른 트랜잭션이 사용할 수있게합니다. –

+1

그렇다면 제대로 거래를 설정해야합니다 ... 그러나 설정에 결함이 있습니다. 왜 당신은'SessionFactory'와'EntitymanagerFactory' 둘 다 사용하고 있습니까? 단일 트랜잭션 관리자 만 사용하고 있습니다. 주요 문제는 설정입니다. –

답변

0

예, 당신이를 플러시 할 필요가 없습니다 수동으로 세션을 종료하면, 최대 절전 모드가 세션을 플러시하는 과정에서 메소드의 조작이 성공하면 트랜잭션. 이 링크 @Transactional이 어떻게 작동하는지에 알 수

확인 - 기본적으로 Spring - @Transactional - What happens in background?

+0

감사 합니다만 session.flush가 없으면 업데이트가 데이터베이스에 반영되지 않습니다. 누락 된 것이 있습니까? –

+1

나는 너를 얻지 못했다. 너 무슨 뜻인지 자세히 설명해 줄 수 있니? – Chaitanya

+0

dao 레이어에 session.flush를 쓰지 않으면 레코드가 데이터베이스에 저장되지 않습니다. 서비스 레이어에서 @transactional을 사용하고 있으므로 설정 문제 나 그 밖의 것이 있습니까? –

0

는 최대 절전 모드는이 마지막으로 데이터베이스에 실행될 때 최적화 할 수 있도록 자사의 쿼리를 스택.

플러시 지점은이 스택을 비우고 트랜잭션에서 데이터베이스로 실행하는 것입니다. 당신 jvm의 "저장"집을 떠난 큰 괴괴 망측 한 데이타베이스에 당신의 질문을 실행하십시오.

이렇게하면 방금 전에 저장 한 것을 선택할 수 없습니다. 아직 데이터베이스에 없습니다.

커밋의 의미는 트랜잭션이 끝나면 끝나며 다른 사람이 데이터베이스를 변경할 수 있도록합니다. 커밋이 실행되면 더 이상 반환 할 수 없습니다.

솔직하게 나는 그것이 최선의 관행인지는 확실하지 않지만 일반적인 CRUD 작업을 위해서는 당신의 DAO 층에 플러시를 추가 할 수 있어야합니다. 이렇게하면 서비스 레이어에 대해 걱정할 필요가 없습니다.

Java에서 트랜잭션을 최적화하려면 서비스 계층에 추가해야합니다. 그러나 성능 문제가 없으면이를 해결할 필요가 없음을 기억하십시오! 귀하의 코드를 서비스 레이어에 플러시하면 코드 가독성이 떨어집니다. 간단하고 어리석은 채로;)