Glassfish实体不会持久化

时间:2016-03-21 20:02:50

标签: jpa glassfish ejb eclipselink jta

我在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时,我看不到日志。 Project是部署servlet的开始,在浏览器中我看到:Served at: /Tets,但是当我检查表时,我看不到我的实体。我做错了什么?

1 个答案:

答案 0 :(得分:0)

简短回答:您滥用应用程序管理的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未声明为线程安全的,因此您需要围绕它的使用进行某种同步。这肯定会杀死所有的表现,所以我建议你回到第一个选项。