简体   繁体   English

如何在Java EE中保留Entity?

[英]How to persist Entity in java EE?

I am trying to add entries to a database through a WebSocket call in java EE, still learning this (I definitely don't understand all the concepts yet). 我试图通过Java EE中的WebSocket调用将条目添加到数据库中,但仍在学习(我肯定还不了解所有概念)。 I get the following two errors depending on how I tweak my code: 根据我如何调整代码,我收到以下两个错误:

Error no 1: java.lang.IllegalStateException: Exception Description: Cannot use an EntityTransaction while using JTA. 错误1:java.lang.IllegalStateException:异常描述:使用JTA时不能使用EntityTransaction。

Error no 2: javax.persistence.TransactionRequiredException 错误2:javax.persistence.TransactionRequiredException

Needless to say I get nothing into my DB. 不用说,我什么也没进入数据库。 There are probably a bunch of stuff in my code and general design that is less than optimal, any advice or pointers are welcome, but the question is where do I go from here to get my user into the Database? 我的代码和一般设计中可能有一堆东西不是最佳的,欢迎任何建议或指针,但是问题是我应该从哪里去使用户进入数据库?

I am working with the following simple setup in order to get something working before tackling the full problem. 我正在使用以下简单设置,以便在解决整个问题之前能够正常工作。

My Entity: 我的实体:

@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;
    }
}

My data access object, In the end this is where the magic DB stuff for User should happen: 我的数据访问对象,最后这应该是User的神奇数据库工作发生的地方:

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;
    }
}

I also have a DatabaseIO, my thinking is that if I have more than just User entity I'd like to collect all the database IO stuff in one class: 我也有一个DatabaseIO,我的想法是,如果我不仅拥有User实体,我想将所有数据库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);
    }
}

Then I have some classes that will use the database IO and handle the requests that come into the application. 然后,我有一些类将使用数据库IO并处理进入应用程序的请求。 Basically the business logic. 基本上是业务逻辑。 I haven't labeled this as a bean as these are created with every user connecting to the application. 我没有将其标记为bean,因为这些是在每个用户连接到应用程序时创建的。 And once they are connected user1 might need to access the SomeClass object of user2, wasn't sure how to accomplish that without creating the objects myself rather than the container. 并且一旦它们连接在一起,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);
    }
}

I have a EJB that starts with the application and holds some status for all of the application, not sure this is the best (most likely there are better ways, my goal was to not put thing I need often in the database until I'm finished with it) way but it's what I've come up with so far: 我有一个从应用程序开始并拥有所有应用程序状态的EJB,但不确定这是最好的(很可能有更好的方法,我的目标是不要将我经常需要的东西放到数据库中,直到完成),但到目前为止,这是我想出的:

@Startup
@Singleton
@Named("some_manager")
public class SomeApplicationManager {

    @PersistenceContext(unitName="AddUsersPU")
    private EntityManager mEM;

    public EntityManager getEM() {
        return mEM;
    }
}

And finally my WebSocket endpoint: 最后是我的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);
            }
        });
    }

}

I've tested this with a simple JavaScript and I get the input I expect until the lines in UserDAO where I've commented that I get an error. 我已经用一个简单的JavaScript进行了测试,得到了我期望的输入,直到UserDAO中的行(我已经注释了)都出现了错误。

EDIT: From what I understand, from the answers below and some more googling, the reason why mEM.persist(user) does not work is because it is not managed by the container. 编辑:据我了解,从下面的答案以及更多的谷歌搜索中,mEM.persist(user)不起作用的原因是因为它不受容器管理。 I tried to remedy this by annotating UserDAO as @Stateless and injecting it through @EJB into DatabaseIO, as suggested. 我试图通过将UserDAO注释为@Stateless并将其通过@EJB注入到DatabaseIO中来进行补救,如建议的那样。 However this gave me a NullPointerException. 但是,这给了我一个NullPointerException。 I then also labeled DatabaseIO and SomeClass as @Stateless and instead of explicitly creating SomeClass in WebEndpoint (and DatabaseIO in SomeClass) I injected it with @EJB. 然后,我还将DatabaseIO和SomeClass标记为@Stateless,而不是在WebEndpoint中显式创建SomeClass(以及SomeClass中的DatabaseIO),而是将其注入@EJB。 At this point I actually got an entity into the database but I'm not sure I understand it all. 在这一点上,我实际上已经将一个实体放入数据库中,但是我不确定我是否理解全部。

Make your UserDAO a Session Bean and use the @PersistenceContext annotation to inject the persistence context inside that. 使您的UserDAO成为会话Bean,并使用@PersistenceContext批注在其中注入持久性上下文。 The reason for your error 1 is you are using JTA and so you are not allowed to manage the transaction, and you will get a transaction when you enter a method of an EJB (unless you specify no transaction explicitly). 错误1的原因是您正在使用JTA,因此不允许您管理事务,并且在输入EJB方法时将获得一个事务(除非您未明确指定事务)。 And you don't need any singleton to supply persistence context, the container will handle it. 而且您不需要任何单例来提供持久性上下文,容器将对其进行处理。

@Stateless
public class UserDAO {

    @PersistenceContext(unitName="AddUsersPU")
    private EntityManager mEM;

And Inject the EJB using @EJB annotation 并使用@EJB注释注入EJB

@EJB
private UserDAO userDao;

Is all you will need, and dont set the EM in that, ie., remove the 这就是您所需要的,不要在其中设置EM,即,删除

public void setEM(EntityManager em)`

method 方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM