#java #jpa #nullpointerexception #cdi #named-entity-recognition
#java #jpa #исключение nullpointerexception #cdi #распознавание именованных объектов
Вопрос:
Прежде чем я получал исключение NullPointerException в этой строке
EntityManager manager = emf.createEntityManager();
но я исправил это, добавив одну строку выше
emf = Persistence.createEntityManagerFactory("main");
Теперь я получаю исключение NullPointerException в этой строке
transaction.begin();
Я не могу понять, почему. Я пытался извлечь его из блока try catch, но получал тот же результат. Также в finally я попытался добавить emf.close(); но ошибка не исправлена. Кроме того, я включаю аннотацию @Named, потому что кто-то предложил мне это сделать.
import java.io.Serializable;
import javax.inject.Named;
import javax.inject.Inject;
import java.sql.*;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceUnit;
import javax.persistence.TypedQuery ;
import javax.transaction.UserTransaction;
import javax.transaction.RollbackException;
import javax.persistence.criteria.*;
import java.util.List;
import java.util.*;
@Named
public class UserManager implements Serializable{
@PersistenceUnit(unitName="main")
private EntityManagerFactory emf;
@Resource
private UserTransaction transaction;
public UserManager() {}
public UserTransaction getTransaction() { return transaction; }
public void setTransaction(UserTransaction transaction) { this.transaction = transaction; }
public void addUser(User v) throws Exception {
emf = Persistence.createEntityManagerFactory("main");
EntityManager manager = emf.createEntityManager();
boolean commit;
try {
transaction.begin();
manager.joinTransaction();
commit = false;
try {
manager.persist(v);
transaction.commit();
commit = true;
}finally {
if(commit==false){
transaction.rollback();
}
}
}finally {
manager.close();
//emf.close();
}
}
@Named("subBean")
@RequestScoped
public class UserBean implements Serializable{
private List<User> users;
private UserManager vm;
private User v;
private int total;
public UserBean() {
this.total= 0;
users = new ArrayList<User>();
vm = new UserManager();
v = new User();
}
public String addUserAction() throws Exception {
vm.addUser(v);
users = getUsers();
return "submit1";
}
//getters and setters
}
Комментарии:
1. Вы объявляете транзакцию, но она не инициализируется. Вызываете ли вы setTransaction() перед вызовом addUser()?
2. @shaunc это должно быть введено CDI.
3. Похоже, вы инициализируете
UserManager
класс вручную, поэтому CDI не может ввести соответствующие переменные. Если вы выполняете работу вручную, вам не следует использовать CDI или следует проверить, соблюдаете ли вы правильный дизайн.4. Я вызываю addUser() из другого класса, который является компонентом CDI и имеет at Named at RequestScoped, и в этом классе у меня есть метод AddUserAction, который вызывает addUser в классе UserManager. У меня есть методы get и setTransaction над методом addUser, но я нигде их не вызываю. Они есть, потому что я использую @Resource приватную транзакцию UserTransaction;
5. @user1282256 предоставьте необходимый код, чтобы увидеть, как вы это делаете.
Ответ №1:
Как отмечалось в моем комментарии, проблема в том, что вы создаете экземпляр UserManager
bean вручную, и CDI не может вводить переменные. Это отмечено здесь:
@Named("subBean")
@RequestScoped
public class UserBean implements Serializable{
//variable is just declared...
private UserManager vm;
public UserBean() {
//and here you're initializing it manually...
vm = new UserManager();
}
//rest of your code...
}
Пусть CDI выполняет свою работу, вводя переменную:
@Named("subBean")
@RequestScoped
public class UserBean implements Serializable{
//variable is just declared
//and notify CDI it should inject an instance when creating an instance of the client class
@Inject
private UserManager vm;
public UserBean() {
//no need to initialize it ever
//vm = new UserManager();
}
//rest of your code...
}
Делая это, вам не нужно будет создавать какое-либо поле, которое также должно быть введено в ваш другой компонент, что означает, что вам не нужно инициализировать emf
поле вручную:
//this line should be commented as well...
//emf = Persistence.createEntityManagerFactory("main");
Комментарии:
1. Спасибо, это решило мою проблему. Также хорошо, что я не закрыл EntityManagerFactory, потому что я смог получить своих пользователей, а также сохранить их в базе данных.