【问题标题】:Add constraint foreign key to entity in JPA将约束外键添加到 JPA 中的实体
【发布时间】:2016-04-23 18:39:36
【问题描述】:

我有一个名为Profile 的实体,它的主键实际上应该是指向RegisteredUser 的外键。

目前,这就是我想说Profile 中的字段既是引用RegisteredUser 的主键又是外键的方式:

@Id
@OneToOne
@JoinColumn(foreignKey = @ForeignKey(name = "REGISTERED_USER_FK"))
private RegisteredUser registeredUser;

RegisteredUser 实体中,我有以下内容:

@OneToOne(cascade = CascadeType.ALL, mappedBy = "registeredUser")
private Profile profile;

不幸的是,当我运行 SpringBootApplication 时,出现以下错误:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'registered_user_username' cannot be null
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_40]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_40]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_40]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[na:1.8.0_40]
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:404) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.Util.getInstance(Util.java:387) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:932) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5094) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994) ~[mysql-connector-java-5.1.38.jar:5.1.38]
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    ... 42 common frames omitted

当我尝试运行这段代码时:

User user = new User("blah");
repo.save(user); // using repositories to store entities to the db

Profile profile = new Profile(user.getFirstName());

RegisteredUser rUser = new RegisteredUser(user.getUsername(), profile);
rur.save(rUser);

我检查了用户的用户名是否为空,但不是...问题是当我保存rUser...

【问题讨论】:

  • registered_user_username属于哪个实体RegisteredUser?
  • 为什么要将个人资料与用户分开? Profile 可以在没有 User 对象的情况下存在吗?
  • @aribeiro 没有这样的专栏。我在RegisteredUser 中有一个名为username 的字段,它也应该是RegisteredUser 的主键,但也应该是引用User 主键的外键...
  • @Funtik 确实应该是一个弱实体,其主键是引用RegisteredUser的外键
  • MySQL 明确指出您正在尝试插入或更新 registered_user_username,因此如果该列不存在:请检查您的 JPA 模型。

标签: java mysql spring hibernate jpa


【解决方案1】:

根据JPA spec,你不能用@Id注解RegisteredUser

我无法想象你为什么需要将个人资料与用户分开,但如果你真的需要这样做,你有几个选择:

选项 A:

Profile 上使用@Embeddable 注释。您不会为 Profile 实体获得单独的表,但您会在 Java 中获得单独的对象。

选项 B:

Profile 上使用@ManyToOne。所以用户的生命周期会是这样的:

  • 创建用户
  • 创建个人资料
  • 保存个人资料
  • 将用户的个人资料设置为已保存的个人资料
  • 保存用户

你甚至可以在这些对象上拥有相同的主键(寻找建议here

选项 C:

配置@OneToOne,但忘记让两个实体具有相同主键的要求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    相关资源
    最近更新 更多