简体   繁体   中英

One-to-one mapping hibernate and not null

I'm new to hibernate and quite new to MySQL too. I have the following two tables:

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
);

In Eclipse, with hibernate tools I have generated the domain code classes. User.java looks like this (siplified):

@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;
    }
}

My issue is with getUserPreferences : of course, that would return null if creating a new user or reading from the db where the corresponding row in the user_detail table does not exist. This is correct, however it forces me to check if userPreferences is not null before accessing its members. And from a coding point of view it is not so handy. So I changed User.getUserPreferences method like this, to get a default value:

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

This is working fine, however if I ever would need to re-generate domain code (User.java) with hibernate tools, that change will be lost. So my question is: is there a way (even by modifying mySQL table/relationships) to automatically have userPreferences always set?

There is no way to do this outside of your code (at least not that I can think of), with some configuration or something like that.

One thing you can do is to initialize the relation when you declare it

private UserPreferences userPreferences = new UserPreferences()

but that also won't survive code regeneration. The only other way I can think of is to put this initialization code into some util method so you can maintain it there regardless of regeneration of entity code.

UserUtils.getUserPreferences(User user)

However, this would only work for the code you write, if some framework needs it you will again get null values because it will not use your util method (the first approach is better in this case).

Do bear in mind that, when you initialize this object on a managed entity, the new object will be persisted into the database.

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

After these lines, you will get a row in user_preferences table if cascade is configured in that manner, or you will get an exception complaining about transient entity found in entity you are trying to persist.

All that being said, is it really that hard to check if something is null, especially if by business rules it is allowed to be null?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM