如何在JavaEE中持久化实体?

如何在JavaEE中持久化实体?,java,jakarta-ee,derby,glassfish-4.1,Java,Jakarta Ee,Derby,Glassfish 4.1,我试图通过JavaEE中的WebSocket调用向数据库添加条目,但仍在学习这一点(我肯定还不理解所有的概念)。根据我如何调整代码,我会出现以下两个错误: 错误1: java.lang.IllegalStateException: 异常描述:使用JTA时无法使用EntityTransaction 错误2: javax.persistence.TransactionRequiredException 不用说,我的数据库里什么也没有。我的代码和一般设计中可能有很多东西不是最优的,欢迎提供任何建议或指

我试图通过JavaEE中的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内容:

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);
    }
}
然后我有一些类将使用数据库IO并处理进入应用程序的请求。基本上是业务逻辑。我没有将其标记为bean,因为这些bean是由连接到应用程序的每个用户创建的。一旦它们连接起来,user1可能需要访问user2的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);
            }
        });
    }

}
@ServerEndpoint(“/WebSocket”)
公共类WebEndpoint{
@注入
SomeApplicationManager映射管理器;
@奥诺彭
公共void onOpen(会话会话,端点配置){
aSession.addMessageHandler(newMessageHandler.Whole(){
@凌驾
消息上的公共void(字符串aUserName){
System.out.println(“新用户:+aUserName”);
SomeClass aClassObj=新的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)`

方法

我做了类似的事情,它对我有效。请看一看似乎很简单,但当我尝试这个时,我得到了一个NullPointerException,我猜这是因为我自己创建了UserDAO(?),容器似乎没有注入EntityManager。(在上面的SomeApplicationManager中)。有没有一种方法可以让我在不自己创建@Stateless UserDAO的情况下获得对它的引用?