我完全陷入了这个问题,也许有人可以提供帮助。
我有两个实体,父母和孩子。 Test1Entity是父级,Test1ChildEntity是子级。当然,伟大的命名。数据库是Mysql,JPA提供者是Hibernate。以下是两个实体的定义:
@Table(name = "Test1", schema = "", catalog = "")
@Entity
public class Test1Entity {
private int id;
@Column(name = "id")
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String name;
@Column(name = "name")
@Basic
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Test1Entity that = (Test1Entity) o;
if (id != that.id) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
private Collection<Test1ChildEntity> test1ChildrenById;
@OneToMany(mappedBy = "test1ByParentId")
public Collection<Test1ChildEntity> getTest1ChildrenById() {
return test1ChildrenById;
}
public void setTest1ChildrenById(Collection<Test1ChildEntity> test1ChildrenById) {
this.test1ChildrenById = test1ChildrenById;
}
}
@Table(name = "Test1_Child", schema = "", catalog = "")
@Entity
public class Test1ChildEntity {
private int id;
@Column(name = "id")
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String name;
@Column(name = "name")
@Basic
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Test1ChildEntity that = (Test1ChildEntity) o;
if (id != that.id) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
private Test1Entity test1ByParentId;
@ManyToOne
@JoinColumn(name = "parent_id")
public Test1Entity getTest1ByParentId() {
return test1ByParentId;
}
public void setTest1ByParentId(Test1Entity test1ByParentId) {
this.test1ByParentId = test1ByParentId;
}
}
尝试在同一事务中插入一个父项和一个子项的代码如下:
@Transactional
public void createItWell(String parentName, String childName) {
Test1Entity parent = new Test1Entity();
parent.setName(parentName);
Test1ChildEntity child = new Test1ChildEntity();
child.setName(childName);
child.setTest1ByParentId(parent);
Set<Test1ChildEntity> mySet = new HashSet<>();
mySet.add(child);
parent.setTest1ChildrenById(mySet);
this.entityManager.persist(parent);
this.entityManager.persist(child);
}
尝试执行此代码时出现以下异常:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`comwork`.`test1_child`, CONSTRAINT `test1_child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `Test1` (`id`))
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1041)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:133)
单独插入其他实体(不涉及任何关系)可以很好地完成。
两个表定义是:
CREATE TABLE `Test1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
LOCK TABLES `Test1` WRITE;
/*!40000 ALTER TABLE `Test1` DISABLE KEYS */;
INSERT INTO `Test1` (`id`, `name`)
VALUES
(6,'Parent');
/*!40000 ALTER TABLE `Test1` ENABLE KEYS */;
UNLOCK TABLES;
# Dump of table Test1_Child
# ------------------------------------------------------------
CREATE TABLE `Test1_Child` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) unsigned NOT NULL,
`name` varchar(20) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`),
CONSTRAINT `test1_child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `Test1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我是JPA的新手,很抱歉这可能是一个微不足道的问题。
谢谢。
答案 0 :(得分:1)
尝试在OneToMany关系上设置Cascade属性:
@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
private Collection<Test1ChildEntity> test1ChildrenById;
答案 1 :(得分:1)
对于遇到此问题的人......实体代码是使用Idea Intellij persistance生成工具生成的。
显然,该工具无法使用@GeneratedValue注释@Id字段,因此在插入第一个(父)实体后禁用了id提取。这样,子实体将插入外键字段的0(显然无效)值。
只需将@GeneratedValue添加到@Id带注释的属性,它就可以正常工作。