首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >防止不必要的级联表更新

防止不必要的级联表更新
EN

Stack Overflow用户
提问于 2015-08-07 22:07:48
回答 2查看 1.6K关注 0票数 1

我正在创建我的第一个基于JPA的项目。为了完整起见,我的应用程序具有几个具有外键关系的表。许多相关表都是规范化的查找表。

考虑表PersonAccount,在accountid上有fk关系:

代码语言:javascript
运行
复制
+-Person----+               
| personid  |               +-Account---+
| accountid*|==============>| accountid |
| ...       |               | ...       |
+-----------+               +-----------+

在前端(JSF),我为新的Person对象创建了一个表单,其中包含一个包含所有帐户的selectOneMenu列表,所选的帐户被添加到新用户中,并正确地插入到数据库中。

但是,Account表也是自动更新的,我无法找到阻止这种情况发生的方法。

我的课程注释如下:

代码语言:javascript
运行
复制
@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;

    ...
代码语言:javascript
运行
复制
@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对象:

代码语言:javascript
运行
复制
public String savePerson()
{
    try
    {
        em.getTransaction().begin();
        person = em.merge( person );
        em.getTransaction().commit();
    }
    catch (Exception e)
    {
        ...

这将导致对Account 中的每个对象进行UPDATE调用

更新

我从代码中删除了EntityManager.merge()调用,UPDATE语句仍然存在。JSF表单会导致支持它的Account对象的自动更新。下面的行来自JPA跟踪:

代码语言:javascript
运行
复制
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的所有selectOneMenu对象都已被修改;如何防止这种情况?先把他们分开?

更新2

我的persistence.xml如下:

代码语言:javascript
运行
复制
<?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对象之后,我分离了它们,如下所示:

代码语言:javascript
运行
复制
public List<Account> getUsrAccounts()
{
    List<Account> accts = em.createNamedQuery( "Account.findAll", Account.class ).getResultList();
    for (Account acct : accts)
        em.detach(acct);
    return accts;
}

然后,当我提交新的Person对象时,只有链接到新PersonAccount由JPA更新。即使这样也是不可取的,我觉得我在某种程度上滥用了JPA。

用JPA使用不可编辑的查找表的正常方法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-10 02:58:37

不要在您的<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>中启用persistence.xml。想出另一种增强策略。

票数 1
EN

Stack Overflow用户

发布于 2015-08-07 22:14:22

尝试向您的@OneToOne映射添加cascade=CascadeType.REFRESH) --这将向您的ORM框架指示只在刷新(同时读取实体)上级联,而在试图只保存这些实体之一时,不要在更新上级联。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31887328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档