Hibernate 弹簧靴JPA不';t将实体附加到会话
我有一个使用SpringBootJPA(SpringBootStarterDataJPA依赖项)的项目,它使用Hibernate作为JPA实现 我自动配置了容器(@EnableAutoConfiguration),并使用EntityManager进行CRUD操作 问题: 我使用这个EntityManager在启动时通过HQL查询加载实体,但是当我想要编辑或删除其中任何一个实体时,我会遇到以下错误 org.springframework.dao.InvalidDataAccessApiUsageException:删除分离的实例com.phistory.data.model.car.car#2;嵌套的异常是java.lang.IllegalArgumentException:删除分离的实例com.phistory.data.model.car.car#2 org.springframework.dao.InvalidDataAccessApiUsageException:实体未被管理;嵌套异常为java.lang.IllegalArgumentException:未管理实体 图书馆:Hibernate 弹簧靴JPA不';t将实体附加到会话,hibernate,jpa,spring-boot,hql,Hibernate,Jpa,Spring Boot,Hql,我有一个使用SpringBootJPA(SpringBootStarterDataJPA依赖项)的项目,它使用Hibernate作为JPA实现 我自动配置了容器(@EnableAutoConfiguration),并使用EntityManager进行CRUD操作 问题: 我使用这个EntityManager在启动时通过HQL查询加载实体,但是当我想要编辑或删除其中任何一个实体时,我会遇到以下错误 org.springframework.dao.InvalidDataAccessApiUsageE
- spring boot starter数据jpa 1.4.4.RELEASE(Hibernate 5.0.11.Final)
@Transactional
@存储库
公共类SqlCarDAOImpl扩展SqlDAOImpl实现SqlCarDAO{
@自动连线
公共SqlCarDAOImpl(EntityManager EntityManager){
超级(实体管理器);
}
@凌驾
公共列表getAll(){
返回super.getEntityManager()
.createQuery(“从汽车到汽车”)
.getResultList();
}
}
父道
@Transactional
@Repository
@Slf4j
@NoArgsConstructor
public abstract class SqlDAOImpl<TYPE extends GenericEntity, IDENTIFIER> implements SqlDAO<TYPE, IDENTIFIER> {
@Getter
@PersistenceContext
private EntityManager entityManager;
public SqlDAOImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void saveOrEdit(TYPE entity) {
if (entity != null) {
if (entity.getId() == null) {
log.info("Saving new entity: " + entity.toString());
this.entityManager.persist(entity);
} else {
log.info("Editing entity: " + entity.toString());
this.entityManager.refresh(entity);
}
}
}
public void delete(TYPE entity) {
if (entity != null) {
log.info("Deleting entity: " + entity.toString());
this.entityManager.remove(entity);
}
}
public Session getCurrentSession() {
return this.entityManager.unwrap(Session.class);
}
}
@Transactional
@存储库
@Slf4j
@诺尔格构装师
公共抽象类SqlDAOImpl实现SqlDAO{
@吸气剂
@持久上下文
私人实体管理者实体管理者;
公共SqlDAOImpl(EntityManager EntityManager){
this.entityManager=entityManager;
}
公共void saveOrEdit(类型实体){
如果(实体!=null){
if(entity.getId()==null){
log.info(“保存新实体:+entity.toString());
this.entityManager.persist(实体);
}否则{
log.info(“编辑实体:+entity.toString());
this.entityManager.refresh(实体);
}
}
}
公共作废删除(类型实体){
如果(实体!=null){
log.info(“删除实体:+entity.toString());
this.entityManager.remove(实体);
}
}
公共会话getCurrentSession(){
返回此.entityManager.unwrap(Session.class);
}
}
为什么我加载的实体没有附加到会话?显然,保存一个新实体可以很好地工作,因为此时不能管理该实体
非常感谢
问候语当您在dao之外调用dao的方法时,实体被分离。 为了保持会话,应该在调用dao方法的方法上定义@Transactional注释 (例如)
公共类CarService{
@事务当您在dao之外调用dao的方法时,实体被分离。
为了保持会话,应该在调用dao方法的方法上定义@Transactional注释
(例如)
公共类CarService{
@事务性如果您确实想要使用Spring数据JPA,为什么要直接使用EntityManager
您在上面发布的所有内容都可以“开箱即用”:
应用程序启动程序:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Spring数据JPA存储库:
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.example.model.CollectionParent;
import java.lang.String;
import java.util.List;
@Repository
public interface CarRepository extends CrudRepository<Car, Long> {
// nearly everything you need comes for free
}
如果您将一个Car实体加载到当前持久性上下文中,对其进行修改并让Hibernate在刷新时存储更改(最好是在数据库事务中),则可以简单地实现更新。这可以通过使用@Transactional
注释的Service/DAO方法轻松实现
分离的实体也可以传递给服务,只需重新连接并使用carRepository.save(detachedAndModifiedCar)
保存即可
甚至您的saveOrEdit方法也只是调用entityManager.refresh(entity)
在现有实体的情况下。这意味着根本没有更新代码,或者我弄错了吗?该实体将只使用数据库中的数据进行更新。如果您确实想要使用Spring数据JPA,为什么要直接使用EntityManager
您在上面发布的所有内容都可以“开箱即用”:
应用程序启动程序:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Spring数据JPA存储库:
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.example.model.CollectionParent;
import java.lang.String;
import java.util.List;
@Repository
public interface CarRepository extends CrudRepository<Car, Long> {
// nearly everything you need comes for free
}
如果您将一个Car实体加载到当前持久性上下文中,对其进行修改并让Hibernate在刷新时存储更改(最好是在数据库事务中),则可以简单地实现更新。这可以通过使用@Transactional
注释的Service/DAO方法轻松实现
分离的实体也可以传递给服务,只需重新连接并使用carRepository.save(detachedAndModifiedCar)
保存即可
甚至您的saveOrEdit方法也只是调用entityManager.refresh(entity)
对于现有实体。这意味着根本没有更新代码,或者我弄错了吗?该实体将只使用数据库中的数据进行更新。我尝试注释我的控制器和方法,而不是使用@Transactional处理实体的版本以及调用getAll()的服务方法,但问题仍然存在。但我注意到的一个变化是在之前的跟踪之后的第二个跟踪:org.springframework.transaction.TransactionSystemException:无法提交JPA事务;嵌套异常是javax.persistence.RollbackException:标记为rollbackOn的事务ly]使用root-cause我尝试注释我的控制器和方法,而不是处理带有@Transactional的实体版本以及调用getAll()的服务方法,但运气不好,问题仍然存在。不过,我注意到的一个变化是,在org.springframework.transaction.TransactionSystemException:Can之前的跟踪之后的第二个跟踪
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.example.model.CollectionParent;
import java.lang.String;
import java.util.List;
@Repository
public interface CarRepository extends CrudRepository<Car, Long> {
// nearly everything you need comes for free
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CarService {
@Autowired
private CarRepository carRepository;
@Transactional
public Iterable<Car> findCars() {
return carRepository.findAll();
}
@Transactional
public void updateCar(final Long carId, ...some other params ...) {
final Car car = carRepository.findOne(carId);
car.setXXX ...use some other params here ...
car.setYYY ...use some other params here ...
}
@Transactional
public void updateCar(final Car detachedAndModifiedCar) {
carRepository.save(detachedAndModifiedCar);
}
...
}