MySQLIntegrityConstraintViolationException:键“ PRIMARY”的条目“ 1”重复

时间:2019-02-09 08:25:14

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

我正在尝试创建两个实体(学生,大学),它们之间具有单向@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的代码有效?为什么在我使用@generationValue时代码有问题?

@结果 区别在于,当使用@GeneratedValue时,hibernate创建保存查询,相对而言,当我手动分配id时,hibernate首先检查数据库中是否存在实体,如果是,则首先更新实体;否则,hibernate会首次对其进行保存。 >

1 个答案:

答案 0 :(得分:1)

您没有定义序列生成器。您可以在数据库中进行操作,然后简单地使用(假设其名称为“ my_seq”):

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

我可以看到,您正在使用MySQL,然后可以使用身份生成方法:

@GeneratedValue(strategy = GenerationType.IDENTITY)

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

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

如果您仅用Student的新实例保存University的每个人,则Student的实体将级联并每次插入该实例,因此违反了约束。发生这种情况是因为new University(1L,"pw")未被管理,并且休眠将其视为新实体-并且因为您没有提供id-它被设置为某些默认值(0L)。使用University savedUni = universityRepository.save(uni);可使休眠状态识别该实体,从而无需执行其他插入操作。