Java 为什么Hibernate在save()上连接不相关的实体
在我的Spring Boot 2.1.8项目中,我有以下实体:Java 为什么Hibernate在save()上连接不相关的实体,java,hibernate,spring-boot,jpa,Java,Hibernate,Spring Boot,Jpa,在我的Spring Boot 2.1.8项目中,我有以下实体: @Entity @Table(name = "teacher") @Where(clause = "active = true") class TeacherEntity { @Id @Column(name = "id") public String id; @Basic @Column(name = "active") public boolean active; @Basic @Column
@Entity
@Table(name = "teacher")
@Where(clause = "active = true")
class TeacherEntity {
@Id
@Column(name = "id")
public String id;
@Basic
@Column(name = "active")
public boolean active;
@Basic
@Column(name = "name")
public String name;
}
@Entity
@Table(name = "course")
class CourseEntity {
@Id
@Column(name = "id")
public int id;
@ManyToOne
@JoinColumn(name = "course_id")
public TeacherEntity teacher;
}
@Entity
@Table(name = "seat")
class SeatEntity {
@Id
@Column(name = "id")
public int id;
@ManyToOne
@JoinColumn(name = "parent_id")
public CourseEntity course;
@Basic
@Column(name = "blabla")
public String blabla;
}
情境:一个有效的课程有一个有效的老师,一个静坐被创造并持续。后来,我们从数据库中加载了Seatenty,修改了它的blabla
字段,并试图保存它
public void updateSeats() {
List<SeatEntity> seats = seatRepository.findAllBy____();
seats.forEach(seat -> {
seat.blabla = "new blabla!";
seat = seatRepository.save(seat); // Exception if Teacher.active = false!
});
}
public void updateSeats(){
List seats=seatRepository.findAllBy____;();
座位。forEach(座位->{
seat.blabla=“新建blabla!”;
seat=seatRepository.save(seat);//Teacher.active=false时异常!
});
}
我得到的例外是:
原因:javax.persistence.EntityNotFoundException:无法找到
com.company.TeacherEntity,id为5770d5e3-d7e8-401e-84c5-bb3d83e2e484
位于org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JPAEEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:162)
位于org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:216)
位于org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:333)
位于org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
位于org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
位于org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1298)
位于org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1161)
位于org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:687)
位于org.hibernate.type.EntityType.resolve(EntityType.java:464)
在org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)上
位于org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:226)
位于org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:160)
位于org.hibernate.loader.loader.initializeEntitiesAndCollections(loader.java:1179)
位于org.hibernate.loader.loader.processResultSet(loader.java:1028)
位于org.hibernate.loader.loader.doQuery(loader.java:964)
在org.hibernate.loader.loader.doQueryAndInitializeNonLazyCollections(loader.java:354)上
在org.hibernate.loader.loader.doQueryAndInitializeNonLazyCollections(loader.java:324)上
位于org.hibernate.loader.loader.loadEntity(loader.java:2401)
位于org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:64)
位于org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:54)
位于org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4312)
位于org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:570)
位于org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:538)
位于org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208)
位于org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:333)
位于org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
位于org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
位于org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1298)
位于org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1161)
位于org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:687)
位于org.hibernate.type.EntityType.resolve(EntityType.java:464)
在org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)上
位于org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:226)
位于org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:160)
位于org.hibernate.loader.loader.initializeEntitiesAndCollections(loader.java:1179)
位于org.hibernate.loader.loader.processResultSet(loader.java:1028)
位于org.hibernate.loader.loader.doQuery(loader.java:964)
在org.hibernate.loader.loader.doQueryAndInitializeNonLazyCollections(loader.java:354)上
在org.hibernate.loader.loader.doQueryAndInitializeNonLazyCollections(loader.java:324)上
为什么Hibernate抱怨加载一个两个连接的表,而这个表与我试图保存的数据无关?这个问题的解决方案是什么?我是否需要编写本机更新查询来避开无意义的连接并保存数据?事实证明,问题是通过将方法包装到事务中解决的:
@Transactional
public void updateSeats() {
// same code as above
}
通过在同一事务中加载和保存,Hibernate不再尝试重新加载整个实体图。与您试图保存的数据无关?你的
seantity
取决于CourseEntity
,它取决于TeacherEntity
。它与此有关,但您的@Where
子句阻止加载非活动教师。您试图保存不完整的数据,这是因为您是这样设计的。也许你不应该有@Where
注释,因为它马上就在你的背后咬了你一口。我正试图更新座位
表上的一列。我已经有了实体。为什么我要浪费时间加入其他表格,而需要做的只是一个简单的更新席位…其中id=xxx
更不用说:1。我个人不是这样设计的(你从来没有继承过别人的代码吗?)。@Where注释已经制作了很长一段时间,没有其他不良影响,所以它没有“马上咬我”3。这个问题特别问为什么Hibernate在只需要更新一个@Basic列的情况下进行连接。如果有的话,我愿意