我正在做一个简单的练习来学习JPA。当我尝试删除一个类型为User的实体时,它包含另一个实体Score的集合(用@OneToMany
注解),我得到这个错误:
java.sql.SQLIntegrityConstraintViolationException: Column 'user' cannot be null
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 20 more
这些是我的课程:
User.java
@Entity
@Table(name = "user")
public class User
{
@Id
private Integer id;
@NotNull
@Size(max = 20)
private String name;
@OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL,orphanRemoval = true)
@JoinColumn(name = "user")
private Collection<Score> scores;
public User() {
}
public User(Integer id, String name, Collection<Score> scores) {
this.id = id;
this.name = name;
this.scores = scores;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection<Score> getScores() {
return scores;
}
public void setScores(Collection<Score> scores) {
this.scores = scores;
}
}
Score.java
@Entity
@Table(name = "score")
public class Score
{
@EmbeddedId
private ScoreId id;
@NotNull
private Integer points;
public Score() {
}
public Score(ScoreId id, Integer points) {
this.id = id;
this.points = points;
}
public ScoreId getId() {
return id;
}
public void setId(ScoreId id) {
this.id = id;
}
public Integer getPoints() {
return points;
}
public void setPoints(Integer points) {
this.points = points;
}
@Override
public boolean equals(Object obj) {
if (obj!=null && getClass()==obj.getClass())
{
Score other = (Score) obj;
return Objects.equals(id, other.id) && Objects.equals(points,other.points);
}
return false;
}
@Override
public int hashCode() {
return id!=null ? points!=null ? id.hashCode()+points.hashCode() : 0 : 0;
}
@Override
public String toString() {
return getClass().getName() + "[id =" + id + ",points = " + points;
}
}
ScoreId.java
@Embeddable
public class ScoreId implements Serializable
{
private Integer user;
@Enumerated(EnumType.STRING)
private Game game;
public ScoreId() {
}
public ScoreId(Integer user, Game game) {
this.user = user;
this.game = game;
}
public Integer getUser() {
return user;
}
public void setUser(Integer user) {
this.user = user;
}
public Game getGame() {
return game;
}
public void setGame(Game game) {
this.game = game;
}
public enum Game
{
HANGMAN,
TRIS
}
@Override
public boolean equals(Object obj) {
if (obj!=null && getClass()==obj.getClass())
{
ScoreId other = (ScoreId) obj;
return Objects.equals(user,other.user) && game==other.game;
}
return false;
}
@Override
public int hashCode()
{
return user!=null ? game!=null ? user.hashCode()+game.hashCode() : 0 : 0;
}
@Override
public String toString() {
return getClass().getName() + "[user = " + user + ",game = " + game + "]";
}
}
Main.java
public class Main {
public static void main(String[] args) {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("UserJPA");
EntityManager em = factory.createEntityManager();
EntityTransaction et = em.getTransaction();
User demetrio = em.createQuery("SELECT u FROM User u WHERE u.name = 'Demetrio'",User.class).getSingleResult();
et.begin();
em.remove(demetrio);
et.commit();
em.close();
factory.close();
}
}
这是生成db的脚本:
CREATE TABLE `user`
(
id INT PRIMARY KEY,
`name` VARCHAR(20) UNIQUE NOT NULL
);
CREATE TABLE score
(
`user` INT,
game ENUM("HANGMAN","TRIS"),
points INT UNSIGNED NOT NULL,
PRIMARY KEY(`user`,game),
FOREIGN KEY (`user`) REFERENCES `user`(id)
ON UPDATE CASCADE
ON DELETE CASCADE
)
我正在使用Hibernate作为JPA实现。我搜索了一个解决方案,但我没有找到任何东西。也许我做错了什么。你能帮助我吗?
3条答案
按热度按时间umuewwlo1#
我看到的实现是绝对正确的,尽管它总是可以改进的。数据库设计是好的。你发布的异常可能根本不存在,但它确实存在。数据库一定有问题。这就是为什么我要求发布表的DDL。我相信你发布的DDL,这让我想到:你做得很对。
我只能猜测。
1.表的引擎是InnoDB,但是InnoDB引擎的状态是什么?它是否工作?它是否活动?使用
SHOW ENGINE INNODB STATUS
查看InnoDB的状态。eni9jsuy2#
我通过将ScoreId的
Integer user
替换为带有@ManyToOne
注解的User user
来解决此问题。这些是我的课程:
User.java
Score.java
ScoreId.java
数据库架构相同。
deyfvvtc3#
在我的例子中,使用了一个Envers,在
deleteAll()
或delete()
上,它试图将类型为2
(已删除)的记录插入到相应的_aud
表中。然而,当它这样做时,记录的所有字段看起来都是
NULL
,但是在_aud
表中,其中一列被标记为“NON-NULL”。从
_aud
表的这些列中删除“非空”修复了该问题。