java 休眠-列不能为空

rsaldnfx  于 2023-01-19  发布在  Java
关注(0)|答案(3)|浏览(151)

我正在做一个简单的练习来学习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实现。我搜索了一个解决方案,但我没有找到任何东西。也许我做错了什么。你能帮助我吗?

umuewwlo

umuewwlo1#

我看到的实现是绝对正确的,尽管它总是可以改进的。数据库设计是好的。你发布的异常可能根本不存在,但它确实存在。数据库一定有问题。这就是为什么我要求发布表的DDL。我相信你发布的DDL,这让我想到:你做得很对。
我只能猜测。
1.表的引擎是InnoDB,但是InnoDB引擎的状态是什么?它是否工作?它是否活动?使用SHOW ENGINE INNODB STATUS查看InnoDB的状态。

eni9jsuy

eni9jsuy2#

我通过将ScoreIdInteger user替换为带有@ManyToOne注解的User user来解决此问题。
这些是我的课程:
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,mappedBy = "id.user")
    private Collection<Score> scores;

    public User() {
    }

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

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

    @Override
    public boolean equals(Object obj) {
        if (obj!=null && getClass()==obj.getClass())
        {
            User other = (User) obj;
            return Objects.equals(id, other.id) && Objects.equals(name, other.name);
        }
        return false;
    }

    @Override
    public String toString() {
        return getClass().getName() + "[id = " + id + ",name = " + name + "]";
    }

    @Override
    public int hashCode() {
        return id!=null ? name!=null ? id.hashCode() + name.hashCode() : 0 : 0;
    }
}

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

    @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 
{
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="user",referencedColumnName = "id")
    private User user;

    @Enumerated(EnumType.STRING)
    private Game game;

    public ScoreId() {
    }

    public ScoreId(User user, Game game) {
        this.user = user;
        this.game = game;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User 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 + "]";
    }
}

数据库架构相同。

deyfvvtc

deyfvvtc3#

在我的例子中,使用了一个Envers,在deleteAll()delete()上,它试图将类型为2(已删除)的记录插入到相应的_aud表中。
然而,当它这样做时,记录的所有字段看起来都是NULL,但是在_aud表中,其中一列被标记为“NON-NULL”。
_aud表的这些列中删除“非空”修复了该问题。

相关问题