2017-01-07 4 views
0

Я пытаюсь добавить записи в базу данных через вызов WebSocket в java EE, все еще изучая это (я определенно не понимаю все концепции). Я получаю следующие две ошибки в зависимости от того, как я настроить мой код:Как сохранить сущность в java EE?

Ошибка № 1: java.lang.IllegalStateException: Исключение Описание: Не удается использовать EntityTransaction при использовании JTA.

Ошибка № 2: javax.persistence.TransactionRequiredException

Излишне говорить, что я ничего не получаю в моей БД. Вероятно, в моем коде и общем дизайне есть куча вещей, которые менее оптимальны, любые советы или указатели приветствуются, но вопрос в том, куда я могу перейти отсюда, чтобы получить моего пользователя в базу данных?

Я работаю со следующей простой настройкой, чтобы получить что-то работающее, прежде чем решать всю проблему.

Мой 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; 
    } 
} 

Мой объект доступа к данным, в конце концов, это где магия DB вещи для пользователя должно произойти:

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-компонент, поскольку они созданы с каждым пользователем, подключающимся к приложению. И как только они будут подключены, пользователю1 может потребоваться доступ к объекту SomeClass пользователя2, не был уверен, как это сделать, не создавая объекты, а не контейнер.

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, где я прокомментировал, что я получаю сообщение об ошибке.

EDIT: Из того, что я понимаю, из приведенных ниже ответов и некоторых других поисковых запросов причина, по которой mEM.persist (пользователь) не работает, заключается в том, что контейнер не управляется им. Я попытался исправить это, аннотируя UserDAO как @Stateless и введя его через @EJB в DatabaseIO, как было предложено. Однако это дало мне исключение NullPointerException. Затем я также обозначил DatabaseIO и SomeClass как @Stateless и вместо явного создания SomeClass в WebEndpoint (и DatabaseIO в SomeClass) я ввел его с помощью @EJB. На данный момент я фактически получил объект в базе данных, но я не уверен, что все это понимаю.

+0

Я сделал что-то похожее на это, и это сработало для меня. Пожалуйста, посмотрите –

ответ

0

Сделайте свой UserDAO сессионным компонентом и используйте аннотацию @PersistenceContext, чтобы вставить контекст персистентности внутри этого. Причина вашей ошибки 1 заключается в том, что вы используете JTA, и вам не разрешено управлять транзакцией, и вы получите транзакцию при вводе метода EJB (если вы явно не укажете транзакцию). И вам не нужен ни один сингл, чтобы обеспечить контекст persistence, контейнер будет обрабатывать его.

@Stateless 
public class UserDAO { 

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

И Инжектируйте EJB с помощью @EJB аннотацию

@EJB 
private UserDAO userDao; 

Есть все, что вам нужно, и Dont установить EM в том, что, то есть., Удалить метод

public void setEM(EntityManager em)` 

+0

Кажется, достаточно просто, но я получаю исключение NullPointerException, когда я пытаюсь это сделать, я предполагаю, что это потому, что я создаю UserDAO самостоятельно (?), Контейнер, похоже, не вводит EntityManager. (Это происходит в моем SomeApplicationManager выше). есть ли способ получить ссылку на @Stateless UserDAO без его создания? –

+0

Да, используйте @EJB. См. Редактирование –