嗨,我有以下关系:
@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的运动员,然后找到Id = 5的壁橱。但是随后,它完全忽略了将运动员添加到waitingList中的其余代码,并且不会将其持久化到数据库中。
现在显示真正的问题是为什么会这样?
解决方案:
除了@Peter的解决方案效果很好之外,我进行了以下更改,而未添加任何层叠类型,更重要的是,没有调用merge方法:
我更改了我的方法获取对象“运动员”的方式。我没有通过提供它作为参数,而是通过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对象?
答案 0 :(得分:1)
如果保存父实体,没有@OneToMany(cascade=CascadeType.ALL)
集合将不会保存。
如果您在事务中更改实体属性,则无需显式调用合并。如果实体不在交易范围之内,则它将被删除。分离的实体为singleAthlete
。需要合并。 容器退出最后一个EJB方法会自动提交事务。
显式调用entityManager.merge(closet)。
答案 1 :(得分:0)
我认为在将“ singleAthlete”添加到列表之前,必须将其保存到数据库,因此在waitingList.add(singleAthlete)之前尝试: entityManager.persist(singleAthlete); 当然,不要忘记合并singleCloset并提交结果:所以您最终调用: entityManager.merge(singleCloset); entityManager.getTransaction()。commit();