Hibernate JPA —— could not insert 或 detach entity passed to persist 或Found shared references 错误
程序员文章站
2022-04-16 08:52:43
...
错误一:
Caused by: org.hibernate.exception.ConstraintViolationException: could not insert:
[com.fsnip.tms.core.template.model.Template],
或detach entity passed to persist错误。
分析:
检查主键生成策略,判断级联增加的数据列是否满足定义的条件,如非空等。(即两点:映射是否正确;插入的数据或级联插入的数据的各列是否满足约束,如非空等)。
如果是自动生成主键值(如自增主键),persistent方法前应该设置id为null。
此外,如果定义与数据库里面的bigint 类型对应的实体属性的数据类型为Long 类型,则该值没有默认值(即使数据库中指定了默认值),插入数据前必须判断其是否为null,为null则设置一个默认值0L。否则会出现类似错误:ERROR org.hibernate.util.JDBCExceptionReporter - Column 'ISREADONLY'
cannot be null
错误二:
Found shared references to a collection
分析:
出现此错误的原因是实体的关联关系的集合不能共享(即使为空)。如下假设:
Teacher 实体与Student 实体为关联关系,且Teacher 与 Student为一对多关系,用Hibernate JPA 在实体类中通过集合体现如下:
1、映射Student 实体中的外键列TEACHER_ID:(省去getter、setter方法)
@ManyToOne(cascade={CascadeType.REFRESH,CascadeType.DETACH},optional=false, fetch = FetchType.LAZY)
@JoinColumn(name="TEACHER_ID")
private Teacher teacher;
说明:CascadeType.REFRESH 指定当参考的Teacher 实体刷新时,该Student 实体对象获取的其Teacher 对象自动刷新;optional=false 指定TEACHER_ID 在教师表中必须存在;@ManyToOne声明为多对一关系。
2、在Teacher 实体中定义Student 集合:(省去getter、setter方法)
@OneToMany(cascade={CascadeType.REMOVE},fetch=FetchType.LAZY,mappedBy="teacher")
private Set<Student> students = new HashSet<Student>();
经过以上定义后,当我在程序中通过需要复制一个Teacher 实体对象时,不能共享其students集合:
Template temp = old;//假设old是通过JPA 获取的
Teacher newT = new Teacher();
//修改相关信息后将新的Teacher 对象插入数据库
newT.setId(null);//假设主键自增
newT.setStudents(temp.getStduents());//执行此语句时不会出错,但再次查找此newT 或 old 时将提示错误二。
//正确做法
newT.setStudents(null);
//如果需为newT增加原来的students 集合数据,则只能通过JPA 将Student集合数据插入数据库(因为第2步中只定义了REMOVE级联操作)