如何正确持久化 javax.persistence.ManyToOne
今天真是我揪头发的日子。
我想保留一个具有 ManyToOne 关系的新对象,其中目标可能存在也可能不存在。
我当前的方法是首先尝试使用唯一属性从数据库读取目标。
如果失败,那么我创建并保留一个新目标。但从日志文件中我可以看到该对象已找到,并且创建和持久部分未被调用。
我将目标属性从源实体设置为目标实体。最后我尝试保留源实体。
最后我得到了“java.lang.IllegalStateException:在同步期间通过未标记级联持久的关系找到了新对象”
这似乎完全是胡说八道。实体刚刚从数据库中读取,为什么级联 PERSIST 是这样的。
我可以提供整个源代码 - 但这都是 Scala,这可能会带来更多困惑,而不是有帮助。
ManyToOne 定义
/**
* 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
我也尝试添加级联持久注释。但这并没有帮助,因为然后我得到了一个独特的约束异常。
坚持例程
/**
* 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
请注意,日志文件中没有看到“创建用户” - 因此发现用户正常。
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 from 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试@persistence.ManyToOne(cascade = CascadeType.PERSIST)
Try
@persistence.ManyToOne(cascade = CascadeType.PERSIST)
确保您在相同的持久性上下文(相同的 EntityManager/事务)中找到目标对象。
还要确保其 Id 已正确映射。
请包含完整的异常堆栈跟踪以及用于保留对象的代码。
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.