How to correctly persist a javax.persistence.ManyToOne
Today is really my hair pulling day.
I would like to persist an new object with an ManyToOne relationship where the target may or may not exist.
My current approach is to first try to read the target fro开发者_C百科m the db using a unique attribute.
If this failes then I create and persist a new target. But from the log files I can see that the object was found and the create and persist part was not called.
The I set the target attribute from the source entity to the target entity. Last I try to persist the source entity.
In the end I get «java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST»
This seem to be complete bollocks. The entiy was just fresly read from the DB, why cascade PERSIST is.
I can provide the whole source - but it is all Scala which might confuse more then it helps.
ManyToOne Definition
/**
* User who's time is recorded.
*/
@persistence.JoinColumn (nullable = false)
@persistence.ManyToOne
private [this] var Benutzer: Benutzer = _
/**
* User who's time is recorded.
*
* @return a copy of the Benutzer
*/
def getBenutzer = this.Benutzer
/**
* Project short name (i.E. "a20999002006")
*
* @param a new Benutzer
*/
def setBenutzer (Benutzer: Benutzer) =
{
if (Benutzer == null )
{
val Exception = new IllegalArgumentException ("Benutzer must be set.")
Zeitstempel.logger.log (logging.Level.FINE, "Throw:", Exception)
throw Exception
}
else
{
this.Benutzer = Benutzer
} // if
} // setBenutzer
I have tried to add a cascade persist annotation as well. But that did not help because then I get a unique constraint exception.
persist routine
/**
* Add a “Kommen” time to the database.
*
* @param uhrzeit Time to record
*/
@javax.annotation.security.RolesAllowed (Array ("employee", "manager"))
override def Add (entry: Zeitstempel) =
{
val Search_Benutzer = entry getBenutzer
val Query_Benutzer = entityManager createNamedQuery "Find_Benutzer_By_User_ID"
Query_Benutzer.setParameter ("ID", Search_Benutzer getUser_ID)
ZeitstempelModel.logger.log (
logging.Level.INFO,
"Search user : {0}",
Search_Benutzer)
val Found_User = try
{
Query_Benutzer.getSingleResult.asInstanceOf[Benutzer]
}
catch
{
case exception: javax.persistence.NoResultException =>
ZeitstempelModel.logger.log (
logging.Level.INFO,
"Create user : {0}",
Query_Benutzer)
entityManager persist Search_Benutzer
Search_Benutzer
} // try
ZeitstempelModel.logger.log (
logging.Level.INFO,
"Found user : {0}",
Found_User)
entry setBenutzer Found_User
entityManager persist entry
} // Add
Note that “Create user” is no where seen in the log file - so the user was found ok.
Try @persistence.ManyToOne(cascade = CascadeType.PERSIST)
Ensure that you find the target object in the same persistence context (same EntityManager/transaction). Also ensure its Id has been mapped correctly. Please include the full exception stack trace, and code you use to persist the object.
精彩评论