我在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
,但是当我检查表时,我看不到我的实体。我做错了什么?
答案 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未声明为线程安全的,因此您需要围绕它的使用进行某种同步。这肯定会杀死所有的表现,所以我建议你回到第一个选项。