Java 为什么Hibernate在save()上连接不相关的实体

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

在我的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(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列的情况下进行连接。如果有的话,我愿意