6

我在使用休眠和合并时遇到了一个奇怪的问题。

有问题的类的结构是这样的:

Project --> CaseWorkerA --|> CaseWorker --|> User

所以基本上我有一个项目类,其中包含对 CaseWorkerA 的引用,它是 CaseWorker 的子类,它又是 User 的子类。

在代码中:

public class Project {
    [...]
    private CaseWorkerA caseWorkerA;

    @ManyToOne(fetch = FetchType.EAGER)
    @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST,
           org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE })
    @JoinColumn(name = "CaseWorker_A")
    public CaseWorkerA getCaseWorkerA() {
        return caseWorkerA;
    }
}

然后我们有用户层次结构:

public class User {
    [...]
}

public class CaseWorker extends User {
    private CaseWorkerStatus status;

    @Enumerated(EnumType.STRING)
    public CaseWorkerStatus getStatus() {
        return status;
    }
    [...]
}

public class CaseWorkerA extends CaseWorker {
    [...]
}

然后,在 Dao 类中有一个方法,用于存储项目:

public class ProjectDao {
    [...]
    public Project saveUpdateProject(final Project project) {
        if (project.getId() == null) {
            getSession(false).save(project);
        } else {
            project = (Project) getSession(false).merge(project);
        }
        getHibernateTemplate().flush();
        return project;
    }
}

现在,问题如下:

Dao 方法接收一个存在于数据库中的项目。此项目连接到 CaseWorkerA,该 CaseWorkerA 的状态为 CaseWorkerStatus.ACTIVE(在数据库和传入对象中)。但是在合并之后,caseworker 的状态变成了 null。

I really don't get how this is possible, since the value is the same in the database, as in the object to be stored, I would expect it to stay the same after the merge.

(There are no triggers in the database for this field..)

(I am going to try to change the dao-method to use saveOrUpdate instead, but even if this will fix the problem I would still very much like to know what caused it in the first place).

Update:

So I fiddled around with the debugger, and found the following: When I queried the session for the CaseWorker in question, it appeared with it's status-field set (actually, the object returned was exactly the one that was connected to the Project).

Doing a saveOrUpdate, and then a get, resulted in a CaseWorker with the status-field set. So it seems to be a problem with the merge method..

4

1 回答 1

0

Managed to figure it out, it turned out that there was a second path from Project to User (lastChangedBy kind of thing), where someone had decided to put cascade for some strange reason. So when the person who last changed the project was a CaseWorker, then the lastChangedBy referenced it as a User, which doesn't know anything about the status, so it was stored a null.

Code:

public class Project {
    private User changedBy;

    @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST,
               org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE })
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "changed_by")
    public User getChangedBy() {
        return this.changedBy;
    }
    [...]
}

The user that was set as changedBy was retrieved from the database like this:

public class UserDao {
    public User getUser(final String userName) {
        return (User) getSession(false).createQuery("from User u where u.loginName = :username").setParameter("username", userName).uniqueResult();
    }
}

Appearantly, even if the user one ends up retrieving is-a CaseWorker, the fields pertaining to a CaseWorker does not get retrieved..

Anyways, removed the uneccesary cascade, and it's all good :)

于 2012-09-04T12:04:04.900 回答