【发布时间】:2019-08-15 14:17:05
【问题描述】:
您好,我有以下关系:
@Entity
public class Athlete implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer athleteId;
@ManyToOne
@JoinColumn(name="closetWaiting")
private Closet closetWaiting;
....
@Entity
public class Closet implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer closetId;
@OneToMany(mappedBy="closetWaiting")
private List<Athlete> waitingList;
....
在我的 Bean 类中,我有以下代码:
public void addAthleteIntoWaitingList(String closetId, Athlete singleAthlete ) {
Closet singleCloset=entityManager.find(Closet.class,Integer.parseInt(closetId));
List<Athlete> waitingList=singleCloset.getWaitingList();
waitingList.add(singleAthlete);
singleCloset.setWaitingList(waitingList);
singleAthlete.setClosetWaiting(singleCloset);
}
这不起作用,因为在我调用方法 addAthleteIntoWaitingList 后,表 Athlete 中的 CLOSETWAITING 列始终为空。
我在这里做错了吗?有什么解决方案的建议吗?
编辑:
为了了解代码背后发生了什么,我在persistence.xml 中激活了eclipse 的日志记录属性。所以这就是我调用该方法时得到的结果:
2019-03-26T10:37:16.862+0100|Fein: SELECT ATHLETEID, FIRSTNAME, GENDER, LASTNAME, PHONENUMBER, closetWaiting FROM ATHLETE WHERE (ATHLETEID = ?)
bind => [12]
2019-03-26T10:37:16.871+0100|Fein: SELECT CLOSETID, CLOSETRANK, GENDER, ISBROKEN, ISOCCUPIED, RESERVATIONENDED, RESERVATIONSTARTED, athleteId FROM CLOSET WHERE (CLOSETID = ?)
bind => [5]
2019-03-26T10:37:16.876+0100|Fein: SELECT CLOSETID, CLOSETRANK, GENDER, ISBROKEN, ISOCCUPIED, RESERVATIONENDED, RESERVATIONSTARTED, athleteId FROM CLOSET
这意味着 JPA 正在获取 Id=12 的 Athlete,然后找到 Id=5 的壁橱。但随后它完全忽略了将运动员添加到等待列表中的其余代码,并且不会将其持久化到数据库中。
现在显示真正的问题是为什么会发生这种情况?
解决方案:
除了@Peter 的解决方案,它运行良好,我做了以下更改,没有添加任何级联类型,更重要的是没有调用合并方法:
我改变了我的方法获取对象 Athlete 的方式。我没有将其作为参数提供,而是通过 EJB Bean 中的 EntityManager.find() 获取它。这是它的外观:
public void addAthleteIntoWaitingList(String closetId, String athleteId ) {
Closet singleCloset=entityManager.find(Closet.class, Integer.parseInt(closetId));
Athlete singleAthlete=entityManager.find(Athlete.class, Integer.parseInt(athleteId));
List<Athlete> waitingList=singleCloset.getWaitingList();
waitingList.add(singleAthlete);
singleCloset.setWaitingList(waitingList);
singleAthlete.setClosetWaiting(singleCloset);
}
谁能向我解释为什么这个有效?我猜是因为我在事务中操纵了一个 Ahtlete 对象吗?
【问题讨论】:
-
您可能没有在事务中运行该代码,或者忘记提交事务。您发布的代码可以改进,但它是正确的。
-
豆类?您是在使用 EJB 事务还是如何持久化壁橱?从哪里调用方法?
-
@PeterŠály 我正在从无状态 LocalBean EJB Bean 调用方法 addAthleteIntoWaitingList。
-
你已经在调用 merge(closet) 了吗?
标签: jpa jakarta-ee entity