【问题标题】:One to one relationship with hibernate annotation与hibernate注解的一对一关系
【发布时间】:2016-05-07 10:18:29
【问题描述】:

我有这部分数据库架构: 还有这个User 实体:

@Entity
@Table(name = "user", catalog = "ats")
public class User implements java.io.Serializable{

    private static final long serialVersionUID = 1L;
    private String username;
    private boolean enabled;
    private Role role;
    private ClientVersion clientVersion;
    private ClientLicense clientLicense;
    @JsonIgnore
    private Set<NotificationHasUser> notificationHasUsers = new HashSet<NotificationHasUser>(0);

    public User() {
    }

    public User(String username, boolean enabled) {
        this.username = username;
        this.enabled = enabled;
    }

    public User(String username, boolean enabled, Role role, Set<NotificationHasUser> notificationHasUsers) {
        this.username = username;
        this.enabled = enabled;
        this.role = role;
        this.notificationHasUsers = notificationHasUsers;
    }

    @Id
    @Column(name = "username", unique = true, nullable = false, length = 45)
    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Column(name = "enabled", nullable = false)
    public boolean isEnabled() {
        return this.enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_role", nullable = false)
    public Role getRole() {
        return this.role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_clientVersion", nullable = false)
    public ClientVersion getClientVersion() {
        return this.clientVersion;
    }

    public void setClientVersion(ClientVersion clientVersion) {
        this.clientVersion = clientVersion;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user")
    public Set<NotificationHasUser> getNotificationHasUser() {
        return this.notificationHasUsers;
    }

    public void setNotificationHasUser(Set<NotificationHasUser> notificationHasUsers) {
        this.notificationHasUsers = notificationHasUsers;
    }

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
    public ClientLicense getClientLicense(){
        return this.clientLicense;
    }

    public void setClientLicense(ClientLicense clientLicense){
        this.clientLicense = clientLicense;
    }
}

在我添加新的客户端许可证之前一切正常。如果我添加这个,我会收到一个无限循环:

Could not write content: Infinite recursion (StackOverflowError) (through reference chain: com.domain.User["clientLicense"]->com.domain.ClientLicense["user"]->com.domain.User["clientLicense"]->com.domain.ClientLicense["user"]->com.domain.User["clientLicense"]->com.domain.ClientLicense["user"]->com.domain.User["clientLicense"]->com.domain.ClientLicense["user"]->com.domain.User["clientLicense"]-....

这是我的ClientLicense 实体

@Entity
@Table(name = "clientlicense", catalog = "ats")
public class ClientLicense implements java.io.Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer idClientLicense;
    private Date startDate;
    private Date endDate;
    private int counter;
    private String macAddress;
    private String cpuId;
    private User user;

        public ClientLicense() {
        }

        /**
         * @param startDate
         * @param endDate
         * @param counter
         * @param macAddress
         * @param cpuId
         * @param users
         */
        public ClientLicense(Date startDate, Date endDate, int counter, String macAddress, String cpuId, User user) {
            super();
            this.startDate = startDate;
            this.endDate = endDate;
            this.counter = counter;
            this.setMacAddress(macAddress);
            this.setCpuId(cpuId);
            this.user = user;
        }

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

        public void setIdClientLicense(Integer idClientLicense) {
            this.idClientLicense = idClientLicense;
        }


        @Column(name = "startDate", nullable = false)
        public Date getStartDate() {
            return this.startDate;
        }

        public void setStartDate(Date startDate) {
            this.startDate = startDate;
        }

        @Column(name = "endDate", nullable = false)
        public Date getEndDate() {
            return this.endDate;
        }

        public void setEndDate(Date endDate) {
            this.endDate = endDate;
        }


        @Column(name = "counter", nullable = false)
        public int getCounter() {
            return this.counter;
        }

        public void setCounter(int counter) {
            this.counter = counter;
        }   

        /**
         * @return the macAddress
         */
        @Column(name = "macAddress", nullable = false)
        public String getMacAddress() {
            return macAddress;
        }

        /**
         * @param macAddress the macAddress to set
         */
        public void setMacAddress(String macAddress) {
            this.macAddress = macAddress;
        }

        /**
         * @return the cpuId
         */
        @Column(name = "cpuId", nullable = false)
        public String getCpuId() {
            return cpuId;
        }

        /**
         * @param cpuId the cpuId to set
         */
        public void setCpuId(String cpuId) {
            this.cpuId = cpuId;
        }

        @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
        @JoinColumn(name = "id_username")
        public User getUser() {
            return this.user;
        }

        public void setUser(User user) {
            this.user = user;
        }
    }

这是我的第一个OneToOne 关系,我必须使用的正确注释是什么?我读了一些例子,但我不明白,它们彼此不同。

【问题讨论】:

  • ClientLicense 是否需要 User 对象?或者它可以只使用用户 ID 吗?
  • 试着把@JsonIgnore放在ClientLicense#user上
  • 我将此注释放在用户类中并且它可以工作,但我无法添加新的客户端许可证,我用示例更新了我的问题

标签: java mysql database hibernate spring-data


【解决方案1】:

试试这样的。

public class User {
    private ClientLicense clientLicense;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
    public ClientLicense getClientLicense() {
        return this.clientLicense;
    }
}

public class ClientLicense {
    private User user;

    @OneToOne
    @JoinColumn(name = "id_username")
    public User getUser() {
        return this.user;
    }
}

【讨论】:

  • 不行,他死循环的问题是json注解。
【解决方案2】:

问题在于这两个实体无法找出这两个字段实际上是在指定一个关系。所以hibernate假定它们不是同一个关系,因此会尝试去获取它们(因为默认情况下会急切地获取一对一的关系)。

在User 类中的clientLicense 字段之前添加@OneToOne(mappedBy = "user"),以告诉hibernate 该字段与ClientLicense 类中的user 字段“映射”在同一列

【讨论】:

  • @luca 没有@JoinColumn 注释?
  • @JoinColumn 在 ClientLicense 实体中
  • @luca 尝试从ClientLicense 中删除@JoinColumn。没有必要这样做。 mappedBy 应该够了。
  • 这是必须的,否则我会收到 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'clientlice0_.user_username' in 'field list'
  • @luca 那是因为休眠表已经存在这样的列。无论如何,这与您的问题无关,代码看起来不错。您是否尝试过删除表格并再次创建它们?也许这两列存在于您的表中,这就是令人困惑的hibernate。或者将休眠设置为update 表定义,而不是使用现有的。
猜你喜欢
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多