@Cacheable杀死Hibernate Session?

时间:2015-09-09 14:20:14

标签: java spring hibernate

自从我在存储库方法上从@QueryHints切换到@Cacheable后,我遇到了一个问题。

我有一个用Spring @Transactional注释的Controller方法,它调用一个Service方法(没有注释)。 该服务首先获得具有repository.getByLogin(login)的实体用户,然后在parent.getChildren()上循环。

@CacheablegetByLogin(login),{I}尝试org.hibernate.LazyInitializationException时有parent.getChildren()

控制器(包含@Transactional 不良做法):

@Controller
@RequestMapping(value="/users")
public class UserController {

    @Autowired
    UserService userService;    

    @Transactional
    @RequestMapping(value="/add-son", method=POST)
    public void addSon(@RequestBody User son) {
        userService.addSon(son);
    }
}

服务:

@Service
public class UserService {

    @Autowired
    UserRepo repository;

    public void addSon(User son) {
        User parent = repository.getByLogin(user.getParent()); // call to my repo
        for(User child: parent.getChildren()) { // breaks here
            System.out.println(child)
        }
        parent.addChild(son);
    }
}

我的旧存储库(已工作):

public interface UserRepo extends JpaRepository<User, Integer> {
    @QueryHints({@QueryHint(name = COMMENT, value = "get user by login"),
                 @QueryHint(name = CACHEABLE, value = "true")})
    User findByLogin(String login);
}

我的新存储库(似乎杀了我的hibernate会话):

public interface UserRepo extends JpaRepository<User, Integer> {
    @Cacheable(value = "myapp.entities.User", cacheManager = "springCacheManager", unless="#result == null")
    User findByLogin(String login);
}

堆栈跟踪:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: myapp.entities.User.children, could not initialize proxy - no Session
        at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
        at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
        at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
        at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
        at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:266)
        at myapp.services.UserService.addSon(UserService.java:19)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:201)
        at com.sun.proxy.$Proxy194.addSon(Unknown Source)
        at myapp.controllers.UserController.addSon(UserController.java:20)
        at myapp.controllers.UserController$$FastClassBySpringCGLIB$$7053b110.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
        at myapp.controllers.UserController$$EnhancerBySpringCGLIB$$66ec522b.addSon(<generated>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

1 个答案:

答案 0 :(得分:1)

当您对实体使用@Cacheable时,您的实体将被添加到缓存中而不会获取延迟集合。当您访问它时,正在加载延迟集合,但是在那段时间会话可能已经结束,并且无法加载延迟集合。 我将使用服务类,其中调用存储库并将实体转换为转换对象(加载延迟集合)。 然后,您将使用转换对象,因此您可以注释服务方法@Cacheable。