我有两个实体,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 Layer
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语句,第二次它应该首先更新父表,然后再更新子表。 然而,它只是在子表上第二次插入。
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`))
答案 0 :(得分:1)
当新行进入CONVERSATION
时,系统会为其分配一个auto_incrementing id
。
您的外键约束通过确保列id
中引用的表BIDIRECTIONAL_ACTIVITIES
中的行中存在相同的conversationId
来强制执行参照完整性(RI) 。这样的行不存在。
也许您不希望设置 RI 。
也许这就是你真正想做的事情:
CREATE TABLE CONVERSATION
(
id bigint(20) PRIMARY KEY,
FOREIGN KEY(id) REFERENCES BIDIRECTIONAL_ACTIVITIES(conversationId)
);
简单地从其中删除AUTO_INCREMENT
方面并手动输入在前一步骤中从某个列conversationId
中的父插入确定的PK ID。
无论如何,你需要重新思考这一切。