我正在尝试创建两个实体(学生,大学),它们之间具有单向@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会首次对其进行保存。 >
答案 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);
可使休眠状态识别该实体,从而无需执行其他插入操作。