2013-06-17 4 views
0

Я полностью застрял в этом вопросе, может быть, кто-то может помочь.JPA вставить родительские и дочерние объекты в ту же транзакцию

У меня есть две сущности, родитель и ребенок. 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, так что извините за то, что, вероятно, является тривиальным вопросом.

спасибо.

ответ

1

Попробуйте установить атрибут Cascade на OneToMany соотношения:

@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) 
private Collection<Test1ChildEntity> test1ChildrenById; 
1

ибо кто работает в этом ... Код объекта был создан с помощью Идеи IntelliJ создания инструмента настойчивости.

По-видимому, инструмент не может аннотировать поля @Id с помощью @GeneratedValue, таким образом отключая выборку идентификатора после того, как вставлен первый (родительский) объект. Таким образом, дочерний объект был вставлен с 0 (явно недопустимым) значением для поля внешнего ключа.

Просто добавьте @GeneratedValue в @Id аннотированное свойство, и оно отлично работает.

Смежные вопросы