问题描述
我正在创建我的第一个基于JPA的项目.我的应用程序具有几个具有外键关系的表,以实现完整性.许多相关的表都是规范化的查找表.
I am creating my first JPA based project. My application features several tables with foreign key relationships for integrity purposes. Many related tables are normalized lookup tables.
考虑在accountid
上具有fk关系的表Person
和Account
:
Consider the tables Person
and Account
, having a fk relationship on accountid
:
+-Person----+
| personid | +-Account---+
| accountid*|==============>| accountid |
| ... | | ... |
+-----------+ +-----------+
在前端(JSF)中,我为包含所有帐户的selectOneMenu
列表的新Person
对象创建了一个表单,并将所选的 accountid 添加到新的人员,它已正确插入数据库中.
In the front end (JSF), I created a form for new Person
objects containing a selectOneMenu
list with all accounts, and the selected accountid is added to the new person which is inserted correctly into the database.
但是,Account
表也会自动更新,我找不到阻止这种情况发生的方法.
However, the Account
table is also updated automatically and I cannot find a way to stop this from happening.
我的班级注释如下:
@Entity
@Table(name="usr_person")
@NamedQuery(name="Person.findAll", query="SELECT u FROM Person u")
public class Person implements Serializable
{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="person_id")
private int personId;
//bi-directional one-to-one association to UsrAccount
@OneToOne
@JoinColumn(name="account_id",insertable=true,updatable=true)
private Account usrAccount;
...
@Entity
@Table(name="usr_account")
@NamedQuery(name="UsrAccount.findAll", query="SELECT u FROM Account u")
public class Account implements Serializable
{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="account_id")
private int accountId;
//bi-directional one-to-one association to UsrPerson
@OneToOne(mappedBy="usrAccount")
private Person usrPerson;
...
前端调用以下方法,该方法仅使用EntityManager
的merge()函数来持久保存新的Person
对象:
The front end calls the below method which simply uses the merge() function of EntityManager
to persist the new Person
object:
public String savePerson()
{
try
{
em.getTransaction().begin();
person = em.merge( person );
em.getTransaction().commit();
}
catch (Exception e)
{
...
这将导致对Account
表中的每个对象进行UPDATE
调用 .
This leads to an UPDATE
call for every object in the Account
table.
更新
我从代码中删除了EntityManager.merge()
调用,并且UPDATE语句仍然存在. JSF表单以某种方式导致支持它的Account
对象的自动更新.以下几行来自JPA跟踪:
I removed the EntityManager.merge()
call from my code and the UPDATE statements are still there. Somehow the JSF form leads to automatic updates of the Account
objects backing it. The lines below are from the JPA trace:
17448 <snip> openjpa.jdbc.SQL - <t 1905431636, conn 233456683> executing prepstmnt 1172878998 UPDATE usr_account SET loginname = ?, password = ?, privileges = ? WHERE account_id = ? [params=(String) mvreijn, (String) ba5edce0be3a9b8f6ac9b84c72935192b2289b3a341ad432021256c7144b59f4, (int) 90, (int) 1]
17449 <snip> openjpa.jdbc.SQL - <t 1905431636, conn 233456683> [1 ms] spent
17449 <snip> openjpa.jdbc.SQL - <t 1905431636, conn 233456683> executing prepstmnt 386904456 UPDATE usr_account SET loginname = ?, password = ?, privileges = ? WHERE account_id = ? [params=(String) afolmer, (String) ba5edce0be3a9b8f6ac9b84c72935192b2289b3a341ad432021256c7144b59f4, (int) 90, (int) 2]
17450 <snip> openjpa.jdbc.SQL - <t 1905431636, conn 233456683> [1 ms] spent
17450 <snip> openjpa.jdbc.SQL - <t 1905431636, conn 233456683> executing prepstmnt 1322606395 UPDATE usr_account SET loginname = ?, password = ?, privileges = ? WHERE account_id = ? [params=(String) annuska, (String) ba5edce0be3a9b8f6ac9b84c72935192b2289b3a341ad432021256c7144b59f4, (int) 80, (int) 3]
17451 <snip> openjpa.jdbc.SQL - <t 1905431636, conn 233456683> [1 ms] spent
这些语句在我commit()
交易时执行.由于某种原因,查询和后续事务导致JPA相信selectOneMenu
中的所有Account
对象都已被修改;我该如何预防呢?首先一个接一个地分离它们吗?
These statements are executed when I commit()
the transaction. For some reason the query and subsequent transaction leads JPA to believe all Account
objects from the selectOneMenu
are modified; how do I prevent this? Detach them first one-by-one?
更新2
我的persistence.xml如下:
My persistence.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="matco">
<class>matco.model.Changelog</class>
<class>matco.model.Item</class>
<class>matco.model.ItemAssignment</class>
<class>matco.model.ItemMaintenance</class>
<class>matco.model.LstType</class>
<class>matco.model.LstColor</class>
<class>matco.model.LstCondition</class>
<class>matco.model.LstSize</class>
<class>matco.model.Team</class>
<class>matco.model.Account</class>
<class>matco.model.Person</class>
<class>matco.model.CatBrand</class>
<class>matco.model.CatItem</class>
<class>matco.model.CatPrice</class>
<class>matco.model.CatSupplier</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/matco" />
<property name="javax.persistence.jdbc.user" value="****" />
<property name="javax.persistence.jdbc.password" value="****" />
<!-- TODO remove this in favor of enhancement -->
<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SCHEMA=TRACE, SQL=TRACE"/>
<property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
</properties>
</persistence-unit>
</persistence>
同时,我在后备bean中查询了Account
对象后,将其分离,如下所示:
Meanwhile, I have detached the Account
objects after I query them in the backing bean, like this:
public List<Account> getUsrAccounts()
{
List<Account> accts = em.createNamedQuery( "Account.findAll", Account.class ).getResultList();
for (Account acct : accts)
em.detach(acct);
return accts;
}
然后,当我提交新的Person
对象时,JPA仅更新链接到新的Person
的Account
.即使那样也是不希望的,而且我感觉到我在某种程度上滥用了JPA.
Then when I commit the new Person
object, only the Account
that is linked to the new Person
is updated by JPA. Even that is undesirable, and I get the feeling that I am misusing JPA in some way.
在JPA中使用不可编辑的查找表的正常方法是什么?
What is the normal way to use a non-editable lookup table with JPA?
推荐答案
在persistence.xml中未启用<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
.找出另一种增强策略.
Do not have <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
enabled in your persistence.xml. Figure out another enhancement strategy.
这篇关于防止不必要的级联表更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!