简体   繁体   中英

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). 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.

Error no 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:

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:

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. Basically the business logic. I haven't labeled this as a bean as these are created with every user connecting to the application. 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.

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:

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

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

    public EntityManager getEM() {
        return mEM;
    }
}

And finally my WebSocket endpoint:

@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.

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. I tried to remedy this by annotating UserDAO as @Stateless and injecting it through @EJB into DatabaseIO, as suggested. However this gave me a 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. 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. 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). 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
private UserDAO userDao;

Is all you will need, and dont set the EM in that, ie., remove the

public void setEM(EntityManager em)`

method

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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