Reputation: 457
I have two entities, BidirectionalActivity(Parent) and Conversation (Child). I want to save parent first and once my Conversation or child is created I want to update parent table and insert in 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)
);
Here is mapping in 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);
}
}
Service Layer:
@Component
public class BidirectionalActivityServiceImpl implements BidirectionalActivityService {
@Autowired
BidirectionalActivityDAO BidirectionalActivityDAO;
@Transactional
@Override
public Integer addBidirectionalActivity(BidirectionalActivity bidirectionalActivity) {
return BidirectionalActivityDAO.addBidirectionalActivity(bidirectionalActivity);
}
My Test Case:
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);
I was expecting hibernate first executes insert statement on parent table and second time it should update parent table first and then child table. however , its just doing insert for second time on child table.
insert into CONVERSATION values ( )
and i am getting error:
Cannot add or update a child row: a foreign key constraint fails (`CONVERSATION`, CONSTRAINT `CONVERSATION_ibfk_1` FOREIGN KEY (`id`) REFERENCES `BIDIRECTIONAL_ACTIVITIES` (`conversationId`))
Upvotes: 1
Views: 1576
Reputation: 24959
What is happening is when a new row goes into CONVERSATION
it is being assigned an auto_incrementing id
by the system.
Your foreign key constraint enforces referential integrity (RI) by making sure that same id
exists in a row in the referenced table BIDIRECTIONAL_ACTIVITIES
in column conversationId
. Such a row does not exist.
Perhaps it is not your desire to have set up your RI as such.
Perhaps this is what you really meant to do:
CREATE TABLE CONVERSATION
(
id bigint(20) PRIMARY KEY,
FOREIGN KEY(id) REFERENCES BIDIRECTIONAL_ACTIVITIES(conversationId)
);
Simply ditching the AUTO_INCREMENT
aspect from it and manually putting in the PK id that is determined from the parent insert in that certain column conversationId
in a prior step.
Regardless, you need to rethink this whole thing.
Upvotes: 1