Hibernate - столбец не может быть нулевым - PullRequest
1 голос
/ 02 марта 2020

Я делаю простое упражнение, чтобы выучить JPA. Когда я пытаюсь удалить объект типа Пользователь , который имеет коллекцию другого объекта Счет (отмечен @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

Это мои классы:

Пользователь. 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;
    } 
}

Оценка. 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. Я искал решение, но ничего не нашел. Может я что то не так делаю. Вы можете мне помочь?

Ответы [ 2 ]

0 голосов
/ 02 марта 2020

Я решил, заменив Integer user из ScoreId на User user с аннотацией @ManyToOne.
Это мои классы:

Пользователь. 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 + "]";
    }
}

Схема базы данных то же самое.

0 голосов
/ 02 марта 2020

Реализация, которую я вижу, абсолютно верна, все это всегда можно улучшить. ДБ-дизайн хорош. Исключение, которое вы публикуете, может просто не существовать, но оно существует. База данных должна иметь проблему. Вот почему я попросил опубликовать DDL таблицы. Я верю в ваш DDL, который вы опубликовали, что заставляет меня задуматься: вы все сделали правильно.

Я могу только догадываться.

  1. Движок таблицы - InnoDB, но каков статус InnoDB-движка? Работает? Это активно? Используйте SHOW ENGINE INNODB STATUS, чтобы увидеть статус InnoDB.
...