【问题标题】:Adding entity doesn't refresh parent's collection添加实体不会刷新父集合
【发布时间】:2012-08-30 07:17:23
【问题描述】:

这个问题很简单,虽然很烦人,我正在寻找一个全球性的解决方案,因为这对我们来说是应用程序范围的问题。

下面的代码真的没什么意思,但我把它贴出来澄清一下!

我们使用带有 JPA 2.0 的 PostgreSQL 数据库,并生成了所有外观和实体,当然我们进行了一些编辑,但实际上并没有太多。

问题在于每个实体都包含其子元素的集合,但是(仅对我们而言?)在创建后不会更新子元素。 对象写入数据库,您可以轻松选择它们,但我们真正希望看到的是刷新后的父对象中的子对象集合。

为什么会这样?如果我们(手动)刷新父 em.refresh(parent) 的实体,它可以解决问题,但我猜这对我们来说意味着在 Facades 中的大量工作。但也许没有别的办法?

感谢支持!

/* 编辑 */

我猜肯定是注释问题或者缓存什么的,不过我已经试过了

@OneToMany(mappedBy = "idquestion", orphanRemoval=true, fetch= FetchType.EAGER) 

@Cacheable(false)

没有正常工作。

/* 编辑 */

一些示例代码以供理解。

数据库级别:

CREATE TABLE Question (
        idQuestion SERIAL,
        questionContent VARCHAR,    
    CONSTRAINT Question_idQuestion_PK PRIMARY KEY (idQuestion)
);

CREATE TABLE Answer (
        idAnswer SERIAL,
        answerContent VARCHAR,
        idQuestion INTEGER,
    CONSTRAINT Answer_idAnswer_PK PRIMARY KEY (idAnswer),
    CONSTRAINT Answer_idQuestion_FK FOREIGN KEY (idQuestion) REFERENCES Question(idQuestion)
);

我们在 Netbeans 7.1 中生成了一些实体,它们看起来都类似于:

@Entity
@Table(name = "question", catalog = "jobfairdb", schema = "public")
@XmlRootElement
@NamedQueries({ BLAH BLAH BLAH...})
public class Question implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name = "idquestion", nullable = false)
    private Integer idquestion;
    @Size(max = 2147483647)
    @Column(name = "questioncontent", length = 2147483647)
    private String questioncontent;
    @OneToMany(mappedBy = "idquestion", orphanRemoval=true) 
    private Collection<Answer> answerCollection;

Getters... setters...

我们(再次)为它们使用生成的外观,都实现了AbstractFacade,例如:

public abstract class CCAbstractFacade<T> {
    private Class<T> entityClass;

    public CCAbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    protected abstract EntityManager getEntityManager();

    public void create(T entity) {
        getEntityManager().persist(entity);
    }

【问题讨论】:

    标签: postgresql jpa jpa-2.0 eclipselink


    【解决方案1】:

    您似乎设置了 ManyToOne,但没有添加到 OneToMany,您必须同时进行。

    在 JPA 和一般 Java 中,您必须更新双向关系的双方,否则对象的状态将不同步。不这样做,在任何 Java 代码中都是错误的,而不仅仅是 JPA。

    JPA 中没有任何魔法可以为您做到这一点。 EclipseLink 确实为此提供了一个神奇的选项,您可以通过自定义程序进行设置 (mapping.setRelationshipPartnerAttributeName()),但不建议这样做,将代码修复为正确是最好的解决方案。

    看, http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Object_corruption.2C_one_side_of_the_relationship_is_not_updated_after_updating_the_other_side

    【讨论】:

      【解决方案2】:

      如果您使用container managed transactions并且您在事务完成后获取集合,父实体会自动更新。否则,您必须自己更新集合。

      这篇文章详细解释了这种行为:JPA implementation patterns: Bidirectional associations

      编辑:

      使用容器托管事务的最简单方法是在persistence.xml 中添加transaction-type="JTA" 并使用Container-Managed Entity Managers

      【讨论】:

      • 哦,我的上帝...是的,这实际上可以解决问题:s 但是我很难相信...有没有办法在实体中使用一些@annotation 来实现双向关联?我不确定我们现在是否使用 CMT:D
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多