如何在 java EE 中持久化实体?
How to persist Entity in java EE?
我正在尝试通过 java EE 中的 WebSocket 调用向数据库添加条目,仍在学习这个(我绝对还不了解所有概念)。根据我调整代码的方式,我收到以下两个错误:
错误 1:
java.lang.IllegalStateException:
异常描述:使用 JTA 时无法使用 EntityTransaction。
错误 2:
javax.persistence.TransactionRequiredException
不用说,我的数据库中什么也没有。我的代码和一般设计中可能有很多东西不是最佳的,欢迎任何建议或指示,但问题是我从这里到哪里才能让我的用户进入数据库?
我正在使用以下简单设置,以便在解决全部问题之前让一些东西正常工作。
我的实体:
@Entity
@Table(name = "USER_TABLE")
public class User implements Serializable {
@Id
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我的数据访问对象,最后这就是用户的神奇数据库东西应该发生的地方:
public class UserDAO {
private EntityManager mEM;
public void save(User user) {
//mEM.getTransaction().begin(); // with comment = error no 2 | no comment = no 1
mEM.persist(user); // I was thinking that this was the magic I needed.
//mEM.getTransaction().commit(); // with comment = error no 2 | no comment = no 1
}
public void setEM(EntityManager em) {
mEM = em;
}
}
我也有一个 DatabaseIO,我的想法是,如果我有的不仅仅是用户实体,我想将所有数据库 IO 的东西收集到一个 class:
public class DatabaseIO {
private EntityManager mEM;
public DatabaseIO(EntityManager em) {
System.out.println("DatabaseIO(" + em + ")");
mEM = em;
}
public void createUser(String name) {
System.out.println("createUser(" + name + ")");
User user = new User();
user.setName(name);
UserDAO userDAO = new UserDAO();
userDAO.setEM(mEM);
userDAO.save(user);
}
}
然后我有一些 classes 将使用数据库 IO 并处理进入应用程序的请求。基本上是业务逻辑。我没有将其标记为 bean,因为它们是在每个连接到应用程序的用户时创建的。一旦他们连接起来,用户 1 可能需要访问用户 2 的 SomeClass 对象,我不确定如何在不自己创建对象而不是容器的情况下实现这一点。
public class SomeClass {
private DatabaseIO mDbIO;
public SomeClass(EntityManager em) {
mDbIO = new DatabaseIO(em);
}
public void newUser(String name) {
mDbIO.createUser(name);
}
}
我有一个从应用程序开始并保存所有应用程序的一些状态的 EJB,不确定这是最好的(很可能有更好的方法,我的目标是不把我经常需要的东西放在数据库,直到我完成它)方式,但这是我到目前为止想出的:
@Startup
@Singleton
@Named("some_manager")
public class SomeApplicationManager {
@PersistenceContext(unitName="AddUsersPU")
private EntityManager mEM;
public EntityManager getEM() {
return mEM;
}
}
最后是我的 WebSocket 端点:
@ServerEndpoint("/WebSocket")
public class WebEndpoint {
@Inject
SomeApplicationManager mAppManager;
@OnOpen
public void onOpen(Session aSession, EndpointConfig aConfig) {
aSession.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String aUserName) {
System.out.println("new user: " + aUserName);
SomeClass aClassObj = new SomeClass(mAppManager.getEM());
aClassObj.newUser(aUserName);
}
});
}
}
我已经用一个简单的 JavaScript 测试了它,我得到了我期望的输入,直到我在 UserDAO 中评论说我收到错误的行。
编辑:根据我的理解,从下面的答案和更多的谷歌搜索,mEM.persist(user) 不起作用的原因是因为它不是由容器管理的。我试图通过将 UserDAO 注释为 @Stateless 并按照建议通过 @EJB 将其注入 DatabaseIO 来解决这个问题。然而,这给了我一个 NullPointerException。然后,我还将 DatabaseIO 和 SomeClass 标记为 @Stateless,而不是在 WebEndpoint 中显式创建 SomeClass(在 SomeClass 中创建 DatabaseIO),我将其注入 @EJB。在这一点上,我实际上在数据库中得到了一个实体,但我不确定我是否理解了所有内容。
使您的 UserDAO 成为会话 Bean,并使用 @PersistenceContext
注释在其中注入持久性上下文。错误 1 的原因是您正在使用 JTA,因此不允许您管理事务,并且当您输入 EJB 的方法时您将获得一个事务(除非您明确指定没有事务)。而且您不需要任何单例来提供持久性上下文,容器会处理它。
@Stateless
public class UserDAO {
@PersistenceContext(unitName="AddUsersPU")
private EntityManager mEM;
并使用 @EJB
注释注入 EJB
@EJB
private UserDAO userDao;
这就是您所需要的,不要在其中设置 EM,即删除
public void setEM(EntityManager em)`
方法
我正在尝试通过 java EE 中的 WebSocket 调用向数据库添加条目,仍在学习这个(我绝对还不了解所有概念)。根据我调整代码的方式,我收到以下两个错误:
错误 1: java.lang.IllegalStateException: 异常描述:使用 JTA 时无法使用 EntityTransaction。
错误 2: javax.persistence.TransactionRequiredException
不用说,我的数据库中什么也没有。我的代码和一般设计中可能有很多东西不是最佳的,欢迎任何建议或指示,但问题是我从这里到哪里才能让我的用户进入数据库?
我正在使用以下简单设置,以便在解决全部问题之前让一些东西正常工作。
我的实体:
@Entity
@Table(name = "USER_TABLE")
public class User implements Serializable {
@Id
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我的数据访问对象,最后这就是用户的神奇数据库东西应该发生的地方:
public class UserDAO {
private EntityManager mEM;
public void save(User user) {
//mEM.getTransaction().begin(); // with comment = error no 2 | no comment = no 1
mEM.persist(user); // I was thinking that this was the magic I needed.
//mEM.getTransaction().commit(); // with comment = error no 2 | no comment = no 1
}
public void setEM(EntityManager em) {
mEM = em;
}
}
我也有一个 DatabaseIO,我的想法是,如果我有的不仅仅是用户实体,我想将所有数据库 IO 的东西收集到一个 class:
public class DatabaseIO {
private EntityManager mEM;
public DatabaseIO(EntityManager em) {
System.out.println("DatabaseIO(" + em + ")");
mEM = em;
}
public void createUser(String name) {
System.out.println("createUser(" + name + ")");
User user = new User();
user.setName(name);
UserDAO userDAO = new UserDAO();
userDAO.setEM(mEM);
userDAO.save(user);
}
}
然后我有一些 classes 将使用数据库 IO 并处理进入应用程序的请求。基本上是业务逻辑。我没有将其标记为 bean,因为它们是在每个连接到应用程序的用户时创建的。一旦他们连接起来,用户 1 可能需要访问用户 2 的 SomeClass 对象,我不确定如何在不自己创建对象而不是容器的情况下实现这一点。
public class SomeClass {
private DatabaseIO mDbIO;
public SomeClass(EntityManager em) {
mDbIO = new DatabaseIO(em);
}
public void newUser(String name) {
mDbIO.createUser(name);
}
}
我有一个从应用程序开始并保存所有应用程序的一些状态的 EJB,不确定这是最好的(很可能有更好的方法,我的目标是不把我经常需要的东西放在数据库,直到我完成它)方式,但这是我到目前为止想出的:
@Startup
@Singleton
@Named("some_manager")
public class SomeApplicationManager {
@PersistenceContext(unitName="AddUsersPU")
private EntityManager mEM;
public EntityManager getEM() {
return mEM;
}
}
最后是我的 WebSocket 端点:
@ServerEndpoint("/WebSocket")
public class WebEndpoint {
@Inject
SomeApplicationManager mAppManager;
@OnOpen
public void onOpen(Session aSession, EndpointConfig aConfig) {
aSession.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String aUserName) {
System.out.println("new user: " + aUserName);
SomeClass aClassObj = new SomeClass(mAppManager.getEM());
aClassObj.newUser(aUserName);
}
});
}
}
我已经用一个简单的 JavaScript 测试了它,我得到了我期望的输入,直到我在 UserDAO 中评论说我收到错误的行。
编辑:根据我的理解,从下面的答案和更多的谷歌搜索,mEM.persist(user) 不起作用的原因是因为它不是由容器管理的。我试图通过将 UserDAO 注释为 @Stateless 并按照建议通过 @EJB 将其注入 DatabaseIO 来解决这个问题。然而,这给了我一个 NullPointerException。然后,我还将 DatabaseIO 和 SomeClass 标记为 @Stateless,而不是在 WebEndpoint 中显式创建 SomeClass(在 SomeClass 中创建 DatabaseIO),我将其注入 @EJB。在这一点上,我实际上在数据库中得到了一个实体,但我不确定我是否理解了所有内容。
使您的 UserDAO 成为会话 Bean,并使用 @PersistenceContext
注释在其中注入持久性上下文。错误 1 的原因是您正在使用 JTA,因此不允许您管理事务,并且当您输入 EJB 的方法时您将获得一个事务(除非您明确指定没有事务)。而且您不需要任何单例来提供持久性上下文,容器会处理它。
@Stateless
public class UserDAO {
@PersistenceContext(unitName="AddUsersPU")
private EntityManager mEM;
并使用 @EJB
注释注入 EJB
@EJB
private UserDAO userDao;
这就是您所需要的,不要在其中设置 EM,即删除
public void setEM(EntityManager em)`
方法