触发器更新后如何将实体Bean与数据库同步

时间:2012-11-14 23:37:25

标签: jpa ejb glassfish-3 ejb-3.1 jta

PostgreSQL 9.1
Glassfish 3.1.2.2
Firefox 10.0.0.7
Linux

我正在使用JPA来持久化PostgreSQL中的实体。但是,有一个表(名为Position)由触发器填充,我使用该表的实体作为只读。实体永远不会将数据保存到此表中,因为它是从触发器加载和操作的。我可以将数据加载到我的托管bean中并查看Position表数据。

我遇到的问题是,一旦触发器修改了数据库(位置表),再次查询位置表时,值仍然相同。位置实体仍包含旧值但尚未重新加载。

这是处理Position实体的bean。我添加了em.flush()没有帮助,也不知道如何以这种方式使用em.refresh()。实际上,如果没有查询,它会如何同步帮助,因为它不知道我想要同步到什么。

任何帮助都非常感激。

EJB ......

@Stateless
public class PositionBean implements IPosition {
    @PersistenceContext(unitName="positionbean-pu")
    private EntityManager em;

    public Position getPositionById(Integer posId) {
        Position pos = null;

        try {
            pos = (Position) em.createNamedQuery("findPosition")
                .setParameter("posId", posId).getSingleResult();
        }
        catch (Exception e) {
            throw new EJBException(e.getMessage());
        }

        return pos;
   }

实体bean ......

@Entity
@SequenceGenerator(name="posIdGen", initialValue=10000,
    sequenceName="pos_seq", allocationSize=1)
@NamedQuery(name="findPosition",
    query="SELECT p FROM Position p WHERE p.posId = :posId")
@Table(name="Position")
public class Position implements Serializable {
    // ...

persistence.xml

<persistence-unit name="positionbean-pu" transaction-type="JTA">
    <jta-data-source>jdbc/postgreSQLPool</jta-data-source>
</persistence-unit>

2 个答案:

答案 0 :(得分:1)

如果有人碰到这个,我学会了如何使用refresh(),这解决了我的问题。

        pos = (Position) em.createNamedQuery("findPosition")
            .setParameter("posId", posId).getSingleResult();

        em.refresh(pos);

答案 1 :(得分:0)

我认为创建“外部”更新的只读实体的正确方法如下:

  1. 按照this answer中所述,通过将注释@Access设置为AccessType.FIELD(或删除注释,因为它是默认的访问类型),对实体类使用基于字段的注释。还应仅按照this answer中的说明提议公众获得者。这样可以防止实体在应用程序中被修改。
  2. 按照this answer中所述,在persistence.xml文件中启用选择性共享缓存模式,并将注释@Cacheable(false)添加到实体类。这会强制JPA在调用EntityManager#find(...)时始终从持久层加载实体。