无法使用remove()方法删除JPA中的子项

时间:2013-09-09 09:23:06

标签: database hibernate jpa parent-child

我已经做了大量的研究,因为某些原因它不适合我,我甚至没有进入我得到“僵尸”实例的情况(就像会话中存在但不再在db中 - 我希望我有这种情况)因为 remove()没有传播到数据库中。子记录继续存在于我的数据库中。

考虑两个表:用户令牌(FK_User_Id),分别为一对多关系

在DAO最终代码中无效:

public void deleteToken(Token t) {

    Token b = em.merge(t);

    em.remove(b); // does nothing

    em.flush();
}

内部控制器:

    Object obj;
    Token token;

    obj = tokenService.getByString(urlToken); // query returning detached object
    User user;

    if (obj != null) {

        token = (Token) obj; // Detached, query is "fetch" overriding lazy init, so token contains its user parent

        user = token.getUser(); // simply get the user to which this token belongs

        if ((token.getExpiryDate().compareTo(new GregorianCalendar()
                .getTime())) == 1) {

            userService.activateUser(user); // user gets merged inside and its relevant property is changed and propagated to db successfully

            tokenService.deleteToken(token); // this line calls DAO method described in snippet above - it fails to delete the token, but no error or exception - record simply stays in database

        model.addAttribute("activationSuccess", "true");


        }...

用户实体:

public class User {

    public static final String FIND_USER_BY_TOKEN = "findUserByToken";
    public static final String FIND_USER_BY_USERNAME = "findUserByUsername";
    public static final String FIND_USER_BY_EMAIL = "findUserByEmail";

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval=true)
    private List<Token> tokens = new ArrayList(); ...

令牌实体:

@Entity
@Table(name = "token")
@NamedQueries({
    @NamedQuery(name=Token.FIND_TOKEN_BY_STRING, query="Select t From Token T where t.tokenString=:string")
})
public class Token {

    public static final String FIND_TOKEN_BY_STRING = "findTokenById";
    @Id
    @GeneratedValue
    Long id;

    @ManyToOne(optional=true)
    private User user; ...

现在,如果我打电话给:

    User c = b.getUser();
            em.remove(c);

在DAO代码段中,它删除了令牌和用户,这不是我想要的。只能删除令牌。

基本上我要做的是通过字符串属性检索Token,以及拥有此标记的用户父级。然后我从令牌中检索此用户并更改用户的一些属性(更改传播到db)。到目前为止一切成功。然后我想删除令牌作为最终操作,但不会删除用户。

我正处于第五个小时,请帮助...我设法将令牌的setId设置为null(传播到db),但它只能让我获得令牌不再拥有但仍然存在于数据库中的点。要删除它,我试图将DAO中的Token与null合并,这让我异常。然后我尝试在用户(从此令牌中检索)中将令牌列表值设置为null,并且它也通过我例外。

我应该如何删除我用其父级检索的子令牌实体,但保留父级存在于db?

SQL Hibernate日志在传递remove方法后显示没有删除查询。

谢谢,

1 个答案:

答案 0 :(得分:1)

如果你没有从用户的令牌列表中取消引用令牌,则级联持久化(你级联所有包含持久性的集合)将导致令牌在某个时刻被复活。您必须清除对子项的所有引用,尤其是当您要删除实体时标记为cascade persist的引用。类似的东西:

if ((token.getExpiryDate().compareTo(new GregorianCalendar()
                .getTime())) == 1) {
    user.getTokens().remove(token);
    userService.activateUser(user); 
    //tokenService.deleteToken(token); //no longer needed due to orphanremoval being true
    model.addAttribute("activationSuccess", "true");
    ...