user2985842
user2985842

Reputation: 457

Update parent entity before inserting child entity

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

Answers (1)

Drew
Drew

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

Related Questions