在尝试通过 REST API 更新资源时,我遇到了使用 Spring 和 Hibernate 时遇到的错误。
我用最少的额外属性简化了案例。
我正在尝试更新名为 Rule
的资源。
Rule
有一个 ThingGroup
,它是一组对象的表示。
Rule
还有一组Event
,代表规则的激活范围。
在应用程序执行期间,运行必须检查该事物组上的某些参数以触发警报。
我的问题是,在下面的规则服务中使用 update
方法时,它会失败并出现此错误。
org.hibernate.PersistentObjectException: detached entity passed to persist: com.smartobjectsecurity.common.domain.rule.Event
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:276)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:221)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy117.findOne(Unknown Source)
at com.smartobjectsecurity.common.service.thing.ThingGroupServiceImpl.find(ThingGroupServiceImpl.java:62)
at com.smartobjectsecurity.common.service.thing.ThingGroupServiceImpl.find(ThingGroupServiceImpl.java:1)
at com.smartobjectsecurity.common.service.GenericServiceImpl.find(GenericServiceImpl.java:1)
at com.smartobjectsecurity.common.service.GenericServiceImpl$$FastClassBySpringCGLIB$$daaa7267.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 com.smartobjectsecurity.common.service.thing.ThingGroupServiceImpl$$EnhancerBySpringCGLIB$$aa452fd7.find(<generated>)
at com.smartobjectsecurity.common.service.rule.RuleServiceImpl.update(RuleServiceImpl.java:219)
下面是 ruleService update
方法。
首先,我需要使用 reactGroup 服务更新关联的 react 组。
@Transactional
public Rule update(final Rule rule, User user) throws UnknownEntityException, MyBadRequestException {
final Long id = rule.getId();
Rule found = null;
try {
found = find(id, user);
found.setEvents(rule.getEvents());
thingGroupService.find(rule.getThingGroup().getId(), user);
found.setThingGroup(rule.getThingGroup());
found = dao.saveAndFlush(found);
} catch (final UnknownEntityException e) {
final UnknownEntityException ex = new UnknownEntityException("UnknownEntity/ResourceException.rule", "update_unknown_rule");
ex.setParameters(new Object[] { id });
throw ex;
}
return found;
}
@Override
@Transactional(rollbackFor = UnknownEntityException.class )
public ThingGroup find(final Long id, User user) throws UnknownEntityException {
logger.debug("-> find, id = " + id);
final ThingGroup found = getDao().findOne(buildSpecificationForIdAndUser(id, user));
if (found == null) {
final UnknownEntityException ex = new UnknownEntityException("UnknownEntity/ResourceException.thingGroup", "unknown_thingGroup");
ex.setParameters(new Object[] { id });
throw ex;
}
logger.debug("<- find : " + found);
return found;
}
这里要求的是 buildSpecificationForIdAndUser
和 buildSpecificationForUser
方法。
它们用于根据用户的权限构建搜索限制。
@Transactional
protected Specification<ENTITY> buildSpecificationForIdAndUser(final ID id,final User user){
return new Specification<ENTITY>() {
@Override
public Predicate toPredicate(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Expression<Long> entityId = root.get("id");
Predicate userPredicate = buildSpecificationForUser(user).toPredicate(root, query, builder);
return builder.and(
builder.equal(entityId, id),
userPredicate
);
}
};
}
@Override
@Transactional
protected Specification<ThingGroup> buildSpecificationForUser(final User user) {
return new Specification<ThingGroup>() {
@Override
public Predicate toPredicate(Root<ThingGroup> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Expression<Collection<User>> managersOfThingGroup = root.get("managers");
Expression<Company> thingGroupCompany = root.get("company");
Predicate isManager = builder.isMember(user, managersOfThingGroup);
Predicate isSameCompany = builder.equal(thingGroupCompany,user.getCompany());
return builder.and(isSameCompany,isManager);
}
};
}
当尝试运行 thingGroupService.find(rule.getThingGroup().getId(), user);
时,Hibernate 突然抛出有关 Event 实体的异常(传递给持久化的分离实体)。
我真的不知道这里出了什么问题。
几天来,我一直在搜索各种论坛,但没有找到问题的原因。
为什么在与事件无关的 ThingGroup
资源上运行查找后,Event
实体突然与 session 分离?
最佳答案
您不必为已附加的实体调用 saveAndFlush
,因此应将服务方法更改为:
found = find(id, user);
thingGroupService.find(rule.getThingGroup().getId(), user);
found.setThingGroup(rule.getThingGroup());
found.setEvents(rule.getEvents());
found
实体已经与当前Session
相关联,因此dirty checking mechanism 检测到所有更改和 child entity state transitions如果启用级联,则传播。
https://stackoverflow.com/questions/31963702/
相关文章:
java - Spring Boot + Spring Data Multi-Tenancy
spring - jar 如何在使用它的 Web 应用程序中传播漏洞?
java - Spring MVC 3.2 - 错误页面的内容协商?
spring - 以编程方式重启 Spring Boot 应用程序
java - 单个 hibernate session 中的多个事务(使用 Spring)
java - 使用spring boot(安全)和keycloak启用角色身份验证?
Java - 避免创建空的子类和接口(interface)或生成 Java 源代码模板