我正在尝试使用实体管理器删除实体。以下是我的课程:
实体类
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "GrandParent", schema = "testDbo")
public class GrandParent implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name = "LADDER_SEQUENCE_ID", unique = true, nullable = false)
protected UUID ladderSequenceId;
@Column(name = "LADDER_ID", unique = true, nullable = false)
protected String ladderId;
@Column(name = "LADDER_NAME")
protected String ladderName;
@Column(name = "LADDER_ACCOUNT_NBR")
protected String ladderAccountNumber;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "ladder")
private List<Parent> ladderRungs;
}
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Parent", schema = "testDbo")
public class Parent implements Serializable{
@Serial
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name = "LADDER_RUNG_SEQUENCE_ID", unique = true, nullable = false)
private UUID ladderRungSequenceId;
@Column(name = "LADDER_ID")
protected String ladderId;
@Column(name = "LADDER_RUNG_NBR")
protected Integer ladderRungNumber;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "LADDER_SEQUENCE_ID", nullable = false)
GrandParent ladder;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "rung")
protected List<Child> rungPositions;
}
@Data
@Entity
@Table(name = "Child" , schema = "testDbo")
public class Child implements Serializable{
@Serial
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name = "LADDER_POSITION_ID", unique = true, nullable = false)
protected UUID ladderPositionId;
@Column(name = "LADDER_RUNG_NBR")
protected Integer ladderRungNumber;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="LADDER_RUNG_SEQUENCE_ID", referencedColumnName = "LADDER_RUNG_SEQUENCE_ID")
protected Parent rung;
}
存储库类
@Repository
public interface GrandParentRepository extends JpaRepository<GrandParent, UUID> {
GrandParent findByLadderIdAndLadderAccountNumber(String ladderId, String accountNumber);
}
数据库服务代码:
@Autowired
private EntityManagerFactory entityManagerFactory;
EntityManager em;
public void ladderDBStartTransaction(){
em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
}
public void deleteGrandParent(String ladderId, String accountNumber){
GrandParent grandParent = grandParentRepository.findByLadderIdAndLadderAccountNumber(ladderId, accountNumber);
log.info("GrandParent Entity : {}", grandParent);
try{
em.remove(grandParent);
em.getTransaction().commit();
}catch (Exception ex){
em.getTransaction().rollback();
}finally {
em.close();
}
}
申请代码:
ladderDBService.ladderDBStartTransaction();
ladderDBService.deleteGrandParent(newLadderId, accountNumber);
日志和异常
GrandParent Entity :
GrandParent{ladderSequenceId=203f0264-7ea7-4aa3-875c-282d161469fd, ladderId='00193', ladderName='TestLadder', ladderAccountNumber='X04977780', ladderRungs=[
Parent{ladderRungSequenceId=70fb2731-367c-4ddc-886b-5a7cb73503e0, ladderId='00193', ladderRungNumber=3, rungPositions=[
Child{ladderPositionId=77baba51-be06-47ff-9568-1dd09bc10075, ladderRungNumber=3}]},
Parent{ladderRungSequenceId=339ff84f-f6a0-413d-9056-a1827783efde, ladderId='00193', ladderRungNumber=1, rungPositions=[
Child{ladderPositionId=c3ee56e8-d8da-4f4c-b7e7-0ddc600d38b3, ladderRungNumber=1}]},
Parent{ladderRungSequenceId=8603c6de-20ba-4923-afd4-4381b4935ba6, ladderId='00193', ladderRungNumber=4, rungPositions=[
Child{ladderPositionId=84e10edc-b688-4265-8bdd-8bb2377be55b, ladderRungNumber=4}]},
Parent{ladderRungSequenceId=fcd2dca9-484e-4e14-9b7b-36979e4d766b, ladderId='00193', ladderRungNumber=2, rungPositions=[
Child{ladderPositionId=088cd0f4-a72c-4366-a70c-d3d8967e5b2e, ladderRungNumber=2},
Child{ladderPositionId=f6750041-56d3-4629-aa29-cca08186ec10, ladderRungNumber=2}]}]}
java.lang.IllegalArgumentException: Removing a detached instance com.model.entities.GrandParent#203f0264-7ea7-4aa3-875c-282d161469fd
at org.hibernate.event.internal.DefaultDeleteEventListener.disallowDeletionOfDetached(DefaultDeleteEventListener.java:191)
at org.hibernate.event.internal.DefaultDeleteEventListener.performDetachedEntityDeletionCheck(DefaultDeleteEventListener.java:179)
at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:106)
at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:943)
我已经浏览了一些关于这个问题的线索,这些线索已经发布在网站上。另外,通过谷歌。看来在删除实体之前,我必须先找到它。因此,尝试遵循相同的步骤。根据日志,在删除之前从数据库检索实体。
问题 我在这里做错了什么?
当您尝试删除已与持久化上下文分离的实体时,会抛出
Removing a detached instance exception
。
在您的情况下,正在使用 grandParentRepository.findByLadderIdAndLadderAccountNumber 中创建的单独 EntityManager 实例检索 grandParent 实体。
这个EntityManager实例与ladderDBStartTransaction中创建的实例不同。因此,当您尝试删除实体时,它会与ladderDBStartTransaction中创建的EntityManager分离,并引发异常。
要删除实体,您需要将其合并到持久化上下文中。这将使实体由 EntityManager 管理,然后您可以删除它。
public void deleteGrandParent(String ladderId, String accountNumber){
GrandParent grandParent = grandParentRepository.findByLadderIdAndLadderAccountNumber(ladderId, accountNumber);
log.info("GrandParent Entity : {}", grandParent);
try{
em.remove(em.contains(grandParent) ? grandParent : em.merge(grandParent));
em.getTransaction().commit();
}catch (Exception ex){
em.getTransaction().rollback();
}finally {
em.close();
}
}
参考文档