Reputation: 51
I defined 2 entities with unidirectional one to many relationship:
in Command.class:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="STOCK_ID", referencedColumnName="id")
public StockDetails getStockDetails() {
return stockDetails;
}
in StockDetails.class:
@Id
public String getId() {
return id;
}
means that Command holds one StockDetails and StockDetails can be in many Commands, but not holding the commands.
I have 2 problems:
object references an unsaved transient instance - save the transient instance before flushing
when the cascade type is MERGE AND I change some details iN StockDetils, and insert new Command with the changed StockDetails, this not Updates the existing record example of what i try:
StockDetails sd1 = new StockDetails("GOOL", "Google Inc");
Command c1 = new Command(123456l, 12345614l, sd1, GlobalVeriables.COMMAND_TYPE_ASK, 200, 300d, 1200d,
new Date(System.currentTimeMillis()), GlobalVeriables.COMMAND_STATUS_OPEN);
commandManager.addNewCommand(c1);
StockDetails sd2 = new StockDetails("GOOL", "Google Inc LTD");
Command c2 = new Command(5674l, 5678l, sd2, GlobalVeriables.COMMAND_TYPE_ASK, 200, 300d, 1200d,
new Date(System.currentTimeMillis()), GlobalVeriables.COMMAND_STATUS_OPEN);
commandManager.addNewCommand(c2);
Please help me solv that :)
Upvotes: 0
Views: 3736
Reputation: 3309
when I'm trying to insert new command with existing StockDetails I got Exception on "cannot insert duplicate key in object..."
I guess this happens if one the following case occurs:
StockDetails
, orset the ID of StockDetails
manually, and do the folloing:
c1.setStockDetails(sd1);
entityManager.persist(c1);
What is happening here is the following:
the entity manager tries to persist c1
. As CascadeType.PERSIST
is in place it tries to propagate the persist operation on sd1
too to find out that there is an entry in the database with the same ID which is causing constraint violation exception.
// start transaction here
StockDetails sd1 = entityManager.find(StockDetails.class, <id_of_existing_stockdetails>);
c1.setStockDetails(sd1);
entityManager.persist(c1);
// commit transaction here
object references an unsaved transient instance - save the transient instance before flushing
You are getting this exception if you are doing the following:
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name="STOCK_ID", referencedColumnName="id")
public StockDetails getStockDetails() {
return stockDetails;
}
and
StockDetails sd1 = new StockDetails("GOOL", "Google Inc");
Command c1 = new Command(123456l, 12345614l, sd1,...);
c1.setStockDetails(sd1);
commandManager.addNewCommand(c1); // assuming this line is saving c1
In this case, you're telling the entity manager to persist c1
assigning it a new sd1
(unsaved instance). Now the entity manager has a problem: you told it to save the id of the StockDetails
in its foreign key field, but the object you associated is not saved yet and does not have an id (because you are telling to propagate MERGE but not PERSIST). That is the reason why you're getting the exception.
You have two options to solve the problem:
First save the sd1
and assign the persistent version to c1
and save it as follows:
// start transaction
entityManager.persist(sd1);
StockDetails sdPersistent = entityManager.find(StockDetails.class, <id>); // where id is the primary key of the newly saved sd1
c1.setStockDetails(sdPersistent);
entityManager.persist(c1);
// commit transaction
or
Change the cascade
attribute to CascadeType.PERSIST
, which is the better option in this case (see above Solution1).
Upvotes: 1