java - 在插入子实体之前更新父实体

标签 java mysql hibernate persistence

我有两个实体,BidirectionalActivity(Parent) 和 Conversation (Child)。 我想先保存父表,一旦创建了我的对话或子表,我想更新父表并插入子表。

Below is my Schema

CREATE TABLE BIDIRECTIONAL_ACTIVITIES (
id bigint(20) NOT NULL AUTO_INCREMENT,
status VARCHAR(255) NOT NULL,
conversationId bigint(20),
PRIMARY KEY(id)
} 

create unique index index_conversationId on BIDIRECTIONAL_ACTIVITIES(conversationId);

CREATE TABLE CONVERSATION (
id bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
FOREIGN KEY(id) REFERENCES BIDIRECTIONAL_ACTIVITIES(conversationId)
);

这是 hibernate OneToOne 中的映射:

@Entity
@Table(name="BIDIRECTIONAL_ACTIVITIES")
public class BidirectionalActivity implements Serializable{
    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    @Column(name="status")
    private String status;

   @OneToOne(fetch = FetchType.LAZY, mappedBy="bidirectionalActivity", cascade=CascadeType.ALL)
    @JoinColumn(name="conversationId")
    private Conversation conversation;
}


@Entity
@Table(name="CONVERSATION")
public class Conversation implements Serializable{
    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
    private BidirectionalActivity bidirectionalActivity;
}

DAO层

public class BidirectionalActivityDAOImpl  implements BidirectionalActivityDAO {
 @Autowired
 private SessionFactory sessionFactory;
 @Override
 public void addBidirectionalActivity(BidirectionalActivity bidirectionalActivity) {
        Session session = this.sessionFactory.getCurrentSession();
        session.saveOrUpdate(bidirectionalActivity);
    }
}

服务层:

@Component
public class BidirectionalActivityServiceImpl implements BidirectionalActivityService {
    @Autowired
    BidirectionalActivityDAO BidirectionalActivityDAO;
    @Transactional
    @Override
    public Integer addBidirectionalActivity(BidirectionalActivity bidirectionalActivity) {
        return BidirectionalActivityDAO.addBidirectionalActivity(bidirectionalActivity);
    }

我的测试用例:

BidirectionalActivity bidirectionalActivity = new BidirectionalActivity();
bidirectionalActivity.setStatus("Active");
Integer persistedIdBiderectionalActivity = bidirectionalActivityService.addBidirectionalActivity(bidirectionalActivity);

Conversation conversation = new Conversation();
conversation.setBidirectionalActivity(persistedBidActvty);
        persistedBidActvty.setConversation(conversation);
   bidirectionalActivityService.addBidirectionalActivity(persistedBidActvty);

我期望 hibernate 首先在父表上执行插入语句,第二次它应该先更新父表,然后再更新子表。 然而,它只是在子表上第二次插入。

insert into CONVERSATION values ( )

我收到错误:

Cannot add or update a child row: a foreign key constraint fails (`CONVERSATION`, CONSTRAINT `CONVERSATION_ibfk_1` FOREIGN KEY (`id`) REFERENCES `BIDIRECTIONAL_ACTIVITIES` (`conversationId`))

最佳答案

发生的事情是当新行进入 CONVERSATION 时它被分配了一个 auto_incrementing id由系统。

您的外键约束通过确保相同的 id 来强制执行参照完整性 (RI)存在于引用 表中的一行 BIDIRECTIONAL_ACTIVITIESconversationId 列中.这样的行不存在。

也许您不希望这样设置您的 RI

也许这就是你真正想做的:

CREATE TABLE CONVERSATION
(
   id bigint(20) PRIMARY KEY,
   FOREIGN KEY(id) REFERENCES BIDIRECTIONAL_ACTIVITIES(conversationId)
);

简单地放弃 AUTO_INCREMENT从它的方面并手动放入从父插入确定的 PK id 到该特定列 conversationId在前面的步骤中。

无论如何,您需要重新考虑这整件事。

关于java - 在插入子实体之前更新父实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35495498/

相关文章:

java - 在不同操作系统中测试java类

mysql - PDO 更新多行

MySQL根据另一个表中的股票从一个表中选择*

java - 构建问题 Spring 3 -hibernate 3 项目

java - hibernate 4 Mssql 2008限制字符串

java - Java Swing 中的 GridBagLayout

java - 使用 Mockito 测试 LoginController

java - 将子类对象添加到父类(super class)列表中

mysql - 创建带有日期列的表

java - 如何使用 Hibernate 和 Struts 创建 Maven 项目