2012-10-18 36 views
5

Tôi gặp sự cố với phiên làm việc trong lớp ẩn danh bên trong trong chế độ ngủ đông với nhà máy phiên làm việc mùa xuân. Đây là mã:Phiên ngủ đông trong lớp bên trong

public class DomainDaoImpl extends BasicDaoImpl<Domain> implements Iterable<Collection<Domain>> { 

... 

@Override 
public Iterator<Collection<Domain>> iterator() { 
    return (new Iterator<Collection<Domain>>() { 
     private int counter = 0; 
     public static final int LIMIT = 100; 

     ... 

     @Override 
     @Transactional(readOnly = true) 
     public Collection<Domain> next() { 
      final Criteria criteria = getCurrentSession().createCriteria(Domain.class); 
      final LinkedHashSet<Domain> result = new LinkedHashSet<Domain>(); 

      List resultList = null; 
      while (!(resultList = criteria.list()).isEmpty()) { 
       criteria.setFirstResult((counter++ * LIMIT) + 1); 
       criteria.setMaxResults(LIMIT); 
       result.addAll(resultList); 
      } 
      return result; 
     } 

     ... 
    }); 

Vấn đề là org.hibernate.HibernateException: Không có phiên tìm thấy cho thread hiện hành này thường xảy ra khi phương pháp DAO không nằm trong giao dịch. Vì vậy, làm thế nào để làm cho nó hoạt động với một lớp bên trong?

Trả lời

1

tôi nghĩ rằng việc xác định @Transactional(readOnly = true) ở cấp lớp bên trong, mùa xuân sẽ không thể phát hiện và áp dụng khía cạnh giao dịch trên đó. vì vậy nó sẽ không hoạt động chắc chắn.

nhưng tôi nghĩ rằng nếu bạn viết một cái gì đó như dưới đây có thể làm việc chắc chắn không phải là 100% (tôi nghi ngờ một lần bạn gọi giao dịch phương pháp lặp đóng)

@Override 
@Transactional(readOnly = true) 
public Iterator<Collection<Domain>> iterator() { 
... 
} 

tùy chọn khác có thể được để người gọi có trách nhiệm giao dịch hoặc viết phương pháp bao bọc trên iterator() như getAllDomain() và áp dụng giao dịch cho phương thức đó.

Giải pháp mà làm việc (nêu trong ý kiến)

có thể bạn có thể làm một số bản vá trong getCurrentSession() như getCurrentSession() từ sessionfactory nếu không có sẵn sau đó sử dụng openSession(), ofcourse bạn phải đóng thủ công nếu phiên mới được mở.

+0

Cảm ơn bạn đã phản hồi, tôi đã thử trước khi yêu cầu không thành công. Và tôi không muốn người gọi chịu trách nhiệm quản lý giao dịch vì tôi không muốn @Transactional trong lớp dịch vụ của mình. –

+1

có thể bạn có thể làm một số bản vá trong 'getCurrentSession()' như getCurrentSession() từ sessionFactory nếu không có sẵn rồi dùng 'openSession()', ofcourse bạn phải đóng nó bằng tay nếu phiên mới được mở. –

+0

nó làm việc :-) anyway, chúng ta hãy chờ xem nếu có một gợi ý khác –

1

Bạn có thể cấu hình khía cạnh thời gian nạp dệt

Dưới đây là ví dụ cơ bản như thế nào để làm điều đó

bối cảnh mùa xuân

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"> 

    <context:component-scan base-package="org.foo.bar" /> 
    <context:annotation-config /> 
    <context:load-time-weaver /> 

    <tx:annotation-driven mode="aspectj" proxy-target-class="true"/> 

    <jdbc:embedded-database id="dataSource"> 
     <jdbc:script location="classpath:schema.sql"/> 
    </jdbc:embedded-database> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="annotatedClasses"> 
      <list> 
       <value>org.foo.bar.MyEntity</value> 
      </list> 
     </property> 
    </bean> 

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

</beans> 

Entity lớp

gói org.foo.bar;

import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.Table; 

@Entity 
@Table(name = "ENTITY") 
public class MyEntity { 

    @Id 
    private long id; 
    private String name; 

    public long getId() { 
     return id; 
    } 

    public void setId(long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Override 
    public String toString() { 
     final StringBuilder sb = new StringBuilder(); 
     sb.append("MyEntity"); 
     sb.append("{id=").append(id); 
     sb.append(", name='").append(name).append('\''); 
     sb.append('}'); 
     return sb.toString(); 
    } 
} 

lớp Đào

gói org.foo.bar;

import org.hibernate.Criteria; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 
import org.springframework.transaction.annotation.Transactional; 

import java.util.Iterator; 
import java.util.NoSuchElementException; 

@Component 
public class MyEntityDao implements Iterable<MyEntity> { 

    @Autowired 
    private SessionFactory sessionFactory; 

    @Override 
    public Iterator<MyEntity> iterator() { 
     return new Iterator<MyEntity>() { 
      private int num = 0; 
      private MyEntity item; 

      @Override 
      @Transactional(readOnly = true) 
      public boolean hasNext() { 
       item = getEntity(); 
       return item != null; 
      } 

      @Override 
      @Transactional(readOnly = true) 
      public MyEntity next() { 
       try { 
        if(item == null) { 
         item = getEntity(); 
         if(item == null) { 
          throw new NoSuchElementException(); 
         } 
        } 
        return item; 
       } finally { 
        item = null; 
       } 
      } 

      @Override 
      public void remove() { 
       throw new UnsupportedOperationException(); 
      } 

      private MyEntity getEntity() { 
       final Criteria criteria = getCurrentSession().createCriteria(MyEntity.class); 
       criteria.setFirstResult(num++); 
       criteria.setMaxResults(1); 
       return (MyEntity) criteria.uniqueResult(); 
      } 
     }; 
    } 

    public Session getCurrentSession() { 
     return sessionFactory.getCurrentSession(); 
    } 
} 

SQL

drop table ENTITY if exists 

create table ENTITY (id bigint generated by default as identity (start with 1), name varchar(255), primary key (id)) 

insert into ENTITY (name) values ('Entity1') 
insert into ENTITY (name) values ('Entity2') 
insert into ENTITY (name) values ('Entity3') 

Đơn vị thi

gói org.foo.quán ba;

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

import static org.junit.Assert.assertEquals; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { 
    "classpath:applicationContext.xml" 
}) 
public class MyEntityDaoTest { 

    @Autowired 
    private MyEntityDao dao; 

    @Test 
    public void testDao() throws Exception { 
     int count = 0; 
     for(MyEntity a : dao) { 
      count++; 
     } 
     assertEquals(3, count); 
    } 

} 

Đây là pom.xml của tôi http://maven.apache.org/xsd/maven-4.0.0.xsd "> 4.0.0

<groupId>org.foo.bar</groupId> 
    <artifactId>spring-aspectj-hibernate</artifactId> 
    <version>1.0</version> 

    <properties> 
     <spring.version>3.1.1.RELEASE</spring.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-aspects</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-orm</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-instrument</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <version>${spring.version}</version> 
      <scope>test</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjweaver</artifactId> 
      <version>1.6.12</version> 
     </dependency> 

     <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-entitymanager</artifactId> 
      <version>4.1.1.Final</version> 
     </dependency> 

     <dependency> 
      <groupId>org.hsqldb</groupId> 
      <artifactId>hsqldb</artifactId> 
      <version>1.8.0.10</version> 
      <scope>test</scope> 
     </dependency> 

     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.10</version> 
      <scope>test</scope> 
     </dependency> 

    </dependencies> 

</project> 

Sau khi tất cả các bạn phải chạy JVM với đối số sau -javaagent:<PATH-TO>/spring-instrument-{vertion}.jar.Để ngăn việc thêm -javaagent tranh luận bạn cũng có thể cấu hình chế độ biên dịch theo thời gian.

Các vấn đề liên quan