【问题标题】:One-to-one mapping hibernate and not null一对一映射休眠且不为空
【发布时间】:2015-01-30 15:40:25
【问题描述】:

我是 hibernate 新手,对 MySQL 也很陌生。 我有以下两个表:

CREATE TABLE storeman.user (
    id INT NOT NULL AUTO_INCREMENT,
    email VARCHAR(80) NOT NULL,
    display_name VARCHAR(50),
    password CHAR(41),
    active BOOLEAN NOT NULL DEFAULT FALSE,
    provisional BOOLEAN NOT NULL DEFAULT FALSE,
    last_login TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE INDEX (email)
);

CREATE TABLE storeman.user_preferences (
    id INT NOT NULL AUTO_INCREMENT,
    notify_login BOOLEAN NOT NULL DEFAULT FALSE,
    PRIMARY KEY (id),
    CONSTRAINT id_foreign FOREIGN KEY (id) REFERENCES user (id) ON DELETE CASCADE
);

在 Eclipse 中,我使用休眠工具生成了域代码类。 User.java 看起来像这样(简化):

@Entity
@Table(name = "user", catalog = "storeman", uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class User implements java.io.Serializable {

    private Integer id;
    [...]
    private UserPreferences userPreferences;

    public User() {
    }


    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    [...]

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
    public UserPreferences getUserPreferences() {
        return this.userPreferences;
    }
}

我的问题是getUserPreferences:当然,如果创建新用户或从user_detail 表中不存在相应行的数据库读取,那将返回null。这是正确的,但是它迫使我在访问其成员之前检查userPreferences 是否不为空。而且从编码的角度来看,它并不是那么方便。所以我改变了User.getUserPreferences这样的方法,以获得默认值:

@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
public UserPreferences getUserPreferences() {
    if (this.userPreferences==null)
        this.userPreferences = new UserPreferences();
    return this.userPreferences;
}

这工作正常,但是如果我需要使用休眠工具重新生成域代码 (User.java),那么该更改将会丢失。所以我的问题是:有没有办法(甚至通过修改 mySQL 表/关系)来自动设置 userPreferences?

【问题讨论】:

    标签: java mysql sql hibernate


    【解决方案1】:

    没有办法在你的代码之外做这个(至少不是我能想到的),通过一些配置或类似的东西。

    您可以做的一件事是在声明关系时对其进行初始化

    private UserPreferences userPreferences = new UserPreferences()
    

    但这也不会在代码重新生成后继续存在。我能想到的唯一另一种方法是将此初始化代码放入某个 util 方法中,这样无论实体代码是否重新生成,您都可以在那里维护它。

    UserUtils.getUserPreferences(User user)
    

    但是,这仅适用于您编写的代码,如果某些框架需要它,您将再次获得空值,因为它不会使用您的 util 方法(在这种情况下,第一种方法更好)。

    请记住,当您在托管实体上初始化此对象时,新对象将被持久化到数据库中。

    User user = userDAO.getUser(id);
    user.getUserPreferences(); // this code initializes the relation (new UserPreference())
    

    在这些行之后,如果cascade 以这种方式配置,您将在user_preferences 表中获得一行,否则您将收到一个异常,抱怨在您试图持久化的实体中发现临时实体。

    话虽如此,检查某个东西是否为空真的那么难吗,尤其是在业务规则允许它为空的情况下?

    【讨论】:

    • 嗯,这并不难,但我很懒! :) 说真的:真正的意义不是检查某些东西是否为空,我只是想看看我是否可以学习 MySQL 和/或休眠的一些“隐藏”功能
    • 我想写“懒惰”,但我们彼此不认识,我不想变得粗鲁 :) 我编辑了我的答案,还有一些要记住的事情,但 AFAIK 没有解决这个懒惰的方法。
    猜你喜欢
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 2012-04-07
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    相关资源
    最近更新 更多