【问题标题】:MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'MySQLIntegrityConstraintViolationException:键“PRIMARY”的重复条目“1”
【发布时间】:2019-07-03 09:50:39
【问题描述】:

我正在尝试创建两个实体(学生、大学),它们之间具有单向 @ManyToOne 关系。大学可以有很多学生。

我不想单独保存它们,我想保存学生和大学应该因为@Cascade而被保存。

在保存第二个学生期间,我遇到了异常:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'

我不知道如何解决这个问题。

我的代码:

@Entity
public class Student {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne(cascade=CascadeType.ALL)
    private University university;

    public Student(String name, University university) {
        this.name = name;
        this.university = university;
    }

    public Student() {
    }
}

@Entity
public class University {

    @Id
    private Long id;

    private String name;

    public University(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public University() {
    }
}

    @Repository
public interface StudentRepository extends JpaRepository<Student,Long> {
}



@SpringBootApplication
public class App implements CommandLineRunner
{
    @Autowired
    private StudentRepository studentRepository;
    @Autowired
    private UniversityRepository universityRepository;

    public static void main( String[] args )
    {
        SpringApplication.run(App.class);
    }

    @Override
    public void run(String... strings) throws Exception {
        Student student = new Student("pawel", new University(1L,"pw"));
        Student student1 = new Student("gawel", new University(1L,"pw"));
        studentRepository. save(student);
        studentRepository.save(student1);
    }
}

我探索过,如果除了大学参考之外我手动设置学生 ID,那么一切正常。

有效的代码:

  @Entity
public class Student {

    @Id
    private Long id;

    private String nazwa;

    @ManyToOne(cascade=CascadeType.ALL)
    private University university;

    public Student(Long id,String nazwa, University university) {
        this.id=id;
        this.nazwa = nazwa;
        this.university = university;
    }

    public Student() {
    }

    public Student(String nazwa) {
        this.nazwa = nazwa;
    }
}

    @Entity
public class University {

    @Id
    private Long id;

    private String name;

    public University(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public University() {
    }
}



  @Repository
public interface StudentRepository extends JpaRepository<Student,Long> {
}

    @SpringBootApplication
public class App implements CommandLineRunner
{
    @Autowired
    private StudentRepository studentRepository;

    public static void main( String[] args )
    {
        SpringApplication.run(App.class);
    }

    @Override
    public void run(String... strings) throws Exception {
        Student student = new Student(1L,"pawel", new University(1L,"pw"));
        Student student1 = new Student(2L,"gawel", new University(1L,"pw"));
        studentRepository. save(student);
        studentRepository.save(student1);
    }
}

为什么手动设置学生 ID 的代码有效?为什么我使用@generatedValue 时代码会出现问题?

@结果 不同之处在于,当使用@GeneratedValue 时,hibernate 创建保存查询,相比之下,当我手动分配 id 时,hibernate 首先检查数据库中是否存在实体,如果是,则实体会更新如果不是休眠第一次保存它。

【问题讨论】:

    标签: java spring hibernate spring-data-jpa hibernate-mapping


    【解决方案1】:

    您没有定义序列生成器。你可以在你的数据库中做,然后简单地使用(假设它的名字是“my_seq”):

    @SequenceGenerator(name="seq",sequenceName="my_seq")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
    

    我可以看到,您使用的是 MySQL,那么您可以使用身份生成方法:

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    

    在您的 id 列定义中与 auto_increment 一起:

    create table student(
        id int not null auto_increment,
        ...
    )
    

    编辑:

    先尝试拯救大学。将此设置为 run 方法的主体:

    University uni = new University(1L,"pw");
    University savedUni = universityRepository.save(uni);
    Student student = new Student("pawel", savedUni);
    Student student1 = new Student("gawel", savedUni);
    studentRepository.save(student);
    studentRepository.save(student1);
    

    如果您只使用University 的新实例保存Students 每个人,那么Students 实体每次都会级联并插入该实例,因此违反了约束。发生这种情况是因为new University(1L,"pw") 不是托管的并且hibernate 将它视为一个新实体——并且因为你没有提供一个id——它被设置为一些默认值(0L)。使用University savedUni = universityRepository.save(uni); 可以让hibernate 识别实体,因此不会进行额外的插入操作。

    【讨论】:

    • 我按照你的建议设置,但除了保持相同的 public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
    • 您是否在列定义中添加了 auto_increment?
    • 我已经更新了答案,提供了如何做到这一点的说明
    • 我现在的学生班级: public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;是你的意思吗?
    • 老兄,不... auto_increment 在表定义中。请再读一遍答案。
    猜你喜欢
    • 2014-05-20
    • 2019-02-15
    • 2016-08-04
    • 2016-07-06
    • 1970-01-01
    • 2019-08-28
    • 2014-02-02
    • 2017-02-17
    • 2013-01-15
    相关资源
    最近更新 更多