【问题标题】:Glassfish entity is not persistedGlassfish 实体未持久化
【发布时间】:2016-03-21 20:02:50
【问题描述】:

我在 PostgreSQL 中创建表和序列:

CREATE SEQUENCE 
    test_id
INCREMENT 1
START 1
MAXVALUE 500;
CREATE TABLE TEST(
    id              NUMERIC PRIMARY KEY DEFAULT NEXTVAL('test_id'),
    name                TEXT NOT NULL UNIQUE,
    name2               TEXT DEFAULT NULL
);

然后我在 Eclipse 中生成实体:

@Entity
@NamedQuery(name="Test.findAll", query="SELECT t FROM Test t")
public class Test implements Serializable {
    private static final long serialVersionUID = 1L;
    private long id;
    private String name;
    private String name2;

    public Test() {
    }


    @Id
    @SequenceGenerator(name="TEST_ID_GENERATOR", sequenceName="TEST_ID", allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TEST_ID_GENERATOR")
    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }


    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public String getName2() {
        return this.name2;
    }

    public void setName2(String name2) {
        this.name2 = name2;
    }

}

然后我尝试将我的实体从 servlet 写入表中:

@PersistenceUnit(name="Tets")
EntityManagerFactory emf; 

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        EntityManager em = emf.createEntityManager();
        Test t = new Test();

        t.setName("jdsfjjd");
        t.setName2("jdsfjjd");
        em.persist(t);

        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

当我部署我的项目并使用该 servlet 时,我看不到日志。项目是部署 servlet 启动,在浏览器中我看到:Served at: /Tets,但是当我检查表格时,我看不到我的实体。我做错了什么?

【问题讨论】:

  • em.persist(..)之后添加em.flush()
  • 我添加并捕获 javax.persistence.TransactionRequiredException:异常描述:此线程当前没有活动的外部管理事务
  • 你必须配置一个事务管理器
  • 感谢您的帮助。但你是什么意思?我使用 glassfish(payara) 我不明白为什么当我对 pk 不使用generet 策略时,会添加实体,但是当我使用序列时,不会启用截断管理器

标签: jpa glassfish ejb eclipselink jta


【解决方案1】:

简短的回答:您滥用了应用程序管理的 EntityManager。

当您在 Java EE 环境中注入 EntityManager 时,它由您的 IoC 容器控制(它几乎总是 EJB 或 CDI 容器)。容器处理业务方法调用上的事务传播和划分,无需对事务机制进行任何手动操作:

@PersistenceContext
private EntityManager em;
...
@TransactionAttribute(REQUIRES_NEW)
public void someMethod(Bean b) {
    em.persist(b);
} // Transaction gets committed and em gets flushed with no extra work

当您改为注入 EntityManagerFactory 时,所有的魔法都会消失。在这种情况下,您需要手动执行事务绑定。你什么都不做,这就是你得到 TransactionRequiredException 的原因。原始示例没有抛出任何内容,因为没有活动事务就不会刷新,因此您的更改会被默默忽略。这看起来像这样:

@Resource
private UserTransaction t;
...
t.begin();
emf.createEntityManager().persist(bean);
t.commit();

在这种情况下,我建议您利用行业最佳实践,将 EntityManager 注入与一些无状态 bean 结合使用,以维护 EM 的线程不安全。然后将您的 EJB 注入此 servlet 并执行您需要的操作。

另一种方法是注入 UserTransaction 并显式调用它的 begin() 方法。 UserTransaction 未声明为线程安全的,因此您需要围绕它的使用进行某种同步。这肯定会扼杀所有的性能,所以我建议你回退到第一个选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-27
    • 2016-03-28
    • 1970-01-01
    • 2014-02-13
    • 2015-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多