通过 JPA 更新实体
Updating entity through JPA
我正在做一个自学项目,当我尝试更新一个绑定到另一个实体的实体时遇到了一个问题。
我正在使用 Spring Boot 1.2.3.RELEASE + jpa.
人:
@Component
@Entity
@Table(name = "Person_sql", uniqueConstraints =
@UniqueConstraint(columnNames = {"name", "passport"}))
public class Person implements AcademyEntity {
@Id
@GeneratedValue
private long id;
private String name;
private Date birthday;
@Column(unique=true)
private String passport;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
private Set<Teacher> teacherSet;
public Person() {
this.birthday = new Date();
studentSet = new HashSet<Student>();
teacherSet = new HashSet<Teacher>();
}
public Person(String name, Date birthday, String passport) {
this.name = name;
this.birthday = birthday;
this.passport = passport;
studentSet = new HashSet<Student>();
teacherSet = new HashSet<Teacher>();
}
getters, setters, equals, hashCode, toString
}
老师
@Component
@Entity
@Table(name = "Teacher_sql")
public class Teacher implements AcademyEntity {
@Id
@GeneratedValue
private long id;
private Date start;
private Date finish;
@ManyToOne
@JoinColumn(nullable = false)
private Person person;
... constructors, getters, setters, equals, hashCode, toString
}
JPAPersonDAO
public interface JPAPersonDAO extends JpaRepository<Person, Long> {
}
JPAPersonService
@Service
public class JPAPersonService implements PersonService {
private JPAPersonDAO jpaPersonDAO;
...
@Override
public boolean saveService(Object object) {
if (object instanceof Person) {
try {
if (validatePerson((Person) object)) {
jpaPersonDAO.save((Person) object);
return true;
}
} catch (RuntimeException e) {
log.error(e);
}
}
return false;
}
...
当我更新不是老师的人时 - 一切都很好。如果我触摸一个老师 - 我会收到此错误:
Person person = new Person();
person.setId(..);
jpaPersonService.saveService(person);
...
WARN 6308 --- [nio-8181-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502
ERROR 6308 --- [nio-8181-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "PERSON_ID"; SQL statement
NULL not allowed for column "PERSON_ID"; SQL statement: update teacher_sql set person_id=null where person_id=? [23502-185]
INFO 6308 --- [nio-8181-exec-6] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
我假设我可能会在这里使用交易 (@Transactional),但我不明白 'how-to'。
感谢您的帮助!
编辑
如果我对相同的实体使用纯休眠(没有 spring 和 jpa),它工作正常。
public class HibernatePersonDAOImpl implements PersonDAO {
...
private boolean saveOrDelete(Person p, boolean delete) {
Session session = hibernateUtils.getSession();
try {
Transaction t = session.beginTransaction();
if (delete) {
session.delete(p);
} else {
session.merge(p);
}
t.commit();
} catch (HibernateException e) {
e.printStackTrace();
return false;
}
return true;
}
错误表明 Teacher
没有 Person
集合。级联时,您需要显式管理层次结构,因此类似以下内容应该有效:
Person person = new Person();
Teacher teacher = new Teacher();
person.addTeacher(teacher);
teacher.setPerson(person);
personService.saveService(person);
嗯,
ERROR 6308 --- [nio-8181-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "PERSON_ID"; SQL statement
NULL not allowed for column "PERSON_ID"; SQL statement: update teacher_sql set person_id=null where person_id=? [23502-185]
error 很明显,说 PERSON_ID 是空的。
你有 id 为实体 person 的构造函数吗?
我认为您在其中一个关系中缺少 mappedBy
参数。
@OneToMany(cascade = CascadeType.ALL, mappedBy="person")
private Set<Teacher> teacherSet;
我正在做一个自学项目,当我尝试更新一个绑定到另一个实体的实体时遇到了一个问题。 我正在使用 Spring Boot 1.2.3.RELEASE + jpa.
人:
@Component
@Entity
@Table(name = "Person_sql", uniqueConstraints =
@UniqueConstraint(columnNames = {"name", "passport"}))
public class Person implements AcademyEntity {
@Id
@GeneratedValue
private long id;
private String name;
private Date birthday;
@Column(unique=true)
private String passport;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
private Set<Teacher> teacherSet;
public Person() {
this.birthday = new Date();
studentSet = new HashSet<Student>();
teacherSet = new HashSet<Teacher>();
}
public Person(String name, Date birthday, String passport) {
this.name = name;
this.birthday = birthday;
this.passport = passport;
studentSet = new HashSet<Student>();
teacherSet = new HashSet<Teacher>();
}
getters, setters, equals, hashCode, toString
}
老师
@Component
@Entity
@Table(name = "Teacher_sql")
public class Teacher implements AcademyEntity {
@Id
@GeneratedValue
private long id;
private Date start;
private Date finish;
@ManyToOne
@JoinColumn(nullable = false)
private Person person;
... constructors, getters, setters, equals, hashCode, toString
}
JPAPersonDAO
public interface JPAPersonDAO extends JpaRepository<Person, Long> {
}
JPAPersonService
@Service
public class JPAPersonService implements PersonService {
private JPAPersonDAO jpaPersonDAO;
...
@Override
public boolean saveService(Object object) {
if (object instanceof Person) {
try {
if (validatePerson((Person) object)) {
jpaPersonDAO.save((Person) object);
return true;
}
} catch (RuntimeException e) {
log.error(e);
}
}
return false;
}
...
当我更新不是老师的人时 - 一切都很好。如果我触摸一个老师 - 我会收到此错误:
Person person = new Person();
person.setId(..);
jpaPersonService.saveService(person);
...
WARN 6308 --- [nio-8181-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502
ERROR 6308 --- [nio-8181-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "PERSON_ID"; SQL statement
NULL not allowed for column "PERSON_ID"; SQL statement: update teacher_sql set person_id=null where person_id=? [23502-185]
INFO 6308 --- [nio-8181-exec-6] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
我假设我可能会在这里使用交易 (@Transactional),但我不明白 'how-to'。
感谢您的帮助!
编辑
如果我对相同的实体使用纯休眠(没有 spring 和 jpa),它工作正常。
public class HibernatePersonDAOImpl implements PersonDAO {
...
private boolean saveOrDelete(Person p, boolean delete) {
Session session = hibernateUtils.getSession();
try {
Transaction t = session.beginTransaction();
if (delete) {
session.delete(p);
} else {
session.merge(p);
}
t.commit();
} catch (HibernateException e) {
e.printStackTrace();
return false;
}
return true;
}
错误表明 Teacher
没有 Person
集合。级联时,您需要显式管理层次结构,因此类似以下内容应该有效:
Person person = new Person();
Teacher teacher = new Teacher();
person.addTeacher(teacher);
teacher.setPerson(person);
personService.saveService(person);
嗯,
ERROR 6308 --- [nio-8181-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "PERSON_ID"; SQL statement
NULL not allowed for column "PERSON_ID"; SQL statement: update teacher_sql set person_id=null where person_id=? [23502-185]
error 很明显,说 PERSON_ID 是空的。
你有 id 为实体 person 的构造函数吗?
我认为您在其中一个关系中缺少 mappedBy
参数。
@OneToMany(cascade = CascadeType.ALL, mappedBy="person")
private Set<Teacher> teacherSet;