自从我从存储库方法上的@QueryHints
转换为@Cacheable
后,我遇到了问题。@Cacheable杀死Hibernate会话?
我有一个控制器方法注释春季@Transactional
,它调用一个服务方法(未注释)。 该服务首先获得一个具有repository.getByLogin(login)
的实体用户,然后在parent.getChildren()
上循环。
随着@Cacheable
上getByLogin(login)
,我有一个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);
}
}
我的旧版本库(worke d):
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的Session):
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)
当您退出某个事务并尝试使用该代理执行CRUD时,会引发LazyInitializedException。因此我认为spring没有配置为@Transactional搜索控制器。还要确保你已经启用了缓存: 。顺便说一下:“我有一个控制器注释@Transactional”..不要这样做!糟糕的建筑。 –
这是一个糟糕的项目框架,确实如此:) 但是它与我的仓库中的@ QueryHints协同工作,所以事务在服务中很好地传播(@Service bean)。 – Pleymor
那么'@ Cacheable'和'@ QueryHints'(用于缓存查询结果!)是完全不同的野兽,并且服务于不同的目的。您不能简单地将hibernate托管对象放入缓存中,因为这也会将其放入缓存中。在休眠级别集成第二级缓存或找出将对象重新连接到会话的方法(这可能很危险,因为基本上可能会遇到共享单个实例的问题,并且存在多个会话!)> –