Errati c поведение EntityManager - PullRequest
0 голосов
/ 16 января 2020

долгое время браузер впервые спрашивает.

Я сталкиваюсь с несколькими проблемами с моим приложением, и я не знаю, есть ли у них что-то общее, меня поражает то, что они этого не делают происходит регулярно или по шаблону, иногда один объект иногда является другим, иногда один и тот же запрос, разделенный секундами, приводит к другому результату. Проблемы заключаются в следующем:

  1. Когда я получаю сущность, она приходит с некоторыми атрибутами правильными (id) и другими null , поэтому, когда я оцениваю, является ли сущность null возвращает false , но когда я пытаюсь работать с одним из атрибутов, он генерирует исключение нулевого указателя
  2. Когда я пытаюсь получить отношение, это возвращает ноль , это я решил путем извлечения отношения с запросом, но я не могу использовать это решение везде
  3. Иногда entityManager закрывается без каких-либо объяснений, я проверяю сеанс иначе открыть его, однако он оценивается как true, но в следующей строке кода, где я пытаюсь выполнить операцию, он выдает закрытый сеанс ошибка
  4. Иногда при сохранении дочернего объекта выдает исключение нулевого указателя на родительскую сущность

Замечания о моей реализации:

  1. Все отношения ленивые
  2. Нет Строка м у ethod есть какие-то отношения
  3. Я использую CriteriaBuilder для своих запросов
  4. Я использую EntityManager для сохранения своих сущностей
  5. Одна из моих ожидающих задач - сохранить изменения для нескольких сущностей в одной транзакции, поэтому в следующем коде это что-то, что я представляю

Сущность сотрудника

@SuppressWarnings("serial")
@SequenceGenerator(name = "seq_id_employees", sequenceName = "seq_id_employees",
                initialValue = 1, allocationSize = 1)
@Entity
@Table(name = "Employees")
public class Employee implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_id_employees")
    @Column(name = "id")
    private long id;

    @Column(name = "name", nullable = false)
    private String name;
    .
    .
    .    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "employee")
    private EmployeeDetail empDetails;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "employee")
    private Set<User> users = new HashSet<User>();
    .
    .
    .
    public EmployeeDetail getEmpDetails() {
        return empDetails;
    }

    public void setEmpDetails(EmployeeDetail empDetails) {
        this.empDetails = empDetails;
    }
    .
    .
    .
    @Override
    public String toString() {
        return "EmployeesEntity [id=" + id + ", name=" + name + ", picture=" + Arrays.toString(picture)
                + ", companyMail=" + companyMail + ", active=" + active + ", maxAuth=" + maxAuth + ", created="
                + created + ", updated=" + updated + "]";
    }
}

Сущность EmployeeDetail

@SuppressWarnings("serial")
@SequenceGenerator(name = "seq_id_emp_details", sequenceName = "seq_id_emp_details",
                initialValue = 1, allocationSize = 1)
@Entity
@Table(name = "Employee_Details")
public class EmployeeDetail implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_id_emp_details")
    @Column(name = "id")
    private long id;

    @Column(name = "phone")
    private String phone;
    .
    .
    .
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "employee_id")
    private Employee employee;
    .
    .
    .
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
    .
    .
    .
    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

}

EmployeeDaoImp

public class EmployeeDaoImp extends BaseDaoImp<Employee, Long> implements BaseDao<Employee> {


    /**
     * @Function saveOrUpdate
     * @EmployeesEntity employeeEntity
     * @return blResult
     * @type boolean
     */
    @Override
    public boolean saveOrUpdate(Employee entity) {

        boolean blResult = false;

        try {
            entTransaction.begin();
            if(entity.getId() == 0){
                entManager.persist(entity);
            } else {
                entManager.merge(entity);
            }
            entTransaction.commit();
            blResult = true;
        } catch (Exception e) {
            if(entTransaction.isActive()) {
                entTransaction.rollback();
            }
            entManager.clear();
            System.out.println(e.getMessage());
            e.printStackTrace();
        }

        return blResult;
    }


    /**
     * @Function delete
     * @EmployeesEntity employeeEntity
     * @return blResult
     * @type boolean
     */
    @Override
    public boolean delete(Employee employeeEntity) {

        boolean blResult = false;

        try {
            //openEntManager();
            entTransaction.begin();
            entManager.remove(employeeEntity);
            entTransaction.commit();
            blResult = true;
        } catch (Exception e) {
            if(entTransaction.isActive()) {
                entTransaction.rollback();
            }
            entManager.clear();
            System.out.println(e.getMessage());
            e.printStackTrace();
        }

        return blResult;
    }


    /**
     * @Function getById
     * @long lngEmployeeId
     * @return employeeEntity
     * @type EmployeesEntity
     */
    @Override
    public Employee getById(long lngEmployeeId) {

        Employee employeeEntity = null;

        try {

            CriteriaBuilder cBuilder = entManager.getCriteriaBuilder();
            CriteriaQuery<Employee> cQuery = cBuilder.createQuery(Employee.class);
            Root<Employee> root = cQuery.from(Employee.class);
            cQuery.where(cBuilder.equal(root.get("id"), lngEmployeeId));

            TypedQuery<Employee> tQuery = entManager.createQuery(cQuery);
            List<Employee> employeesList = tQuery.getResultList();
            if (!employeesList.isEmpty()) {
                employeeEntity = employeesList.get(0);
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        return employeeEntity;
    }


    /**
     * @Function getList
     * @return employeesList
     * @type List<EmployeesEntity>
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Employee> getList() {

        List<Employee> employeesList = new ArrayList<Employee>();

        try {
            CriteriaBuilder cBuilder = entManager.getCriteriaBuilder();
            CriteriaQuery<Employee> cQuery = cBuilder.createQuery(Employee.class);
            Root<Employee> root = cQuery.from(Employee.class);
            List<Order> listOrder = new ArrayList<Order>();
            listOrder.add(cBuilder.desc(root.get("id")));
            cQuery.orderBy(listOrder);
            cQuery = this.searchParameters(cBuilder, cQuery, root);

            TypedQuery<Employee> tQuery = entManager.createQuery(cQuery);
            employeesList = tQuery.getResultList();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        return employeesList;
    }


    /**
     * @Function search
     * @long lngEmployeeId
     * @long lngPositionId
     * @int intActive
     * @return employeesList
     * @type List<EmployeesEntity>
     */
    public List<Employee> search(long lngEmployeeId, long lngPositionId, int intActive) {

        List<Employee> employeesList = new ArrayList<Employee>();

        try {

            CriteriaBuilder cBuilder = entManager.getCriteriaBuilder();
            CriteriaQuery<Employee> cQuery = cBuilder.createQuery(Employee.class);
            Root<Employee> root = cQuery.from(Employee.class);
            root.fetch("empDetails"); //Solution problem 2

            List<Predicate> predicates = new ArrayList<Predicate>();
            List<Order> listOrder = new ArrayList<Order>();
            listOrder.add(cBuilder.desc(root.get("id")));
            cQuery.orderBy(listOrder);

            if (lngEmployeeId > 0) {
                predicates.add(cBuilder.equal(root.get("id"), lngEmployeeId));
            }
            if (lngPositionId > 0) {
                predicates.add(cBuilder.equal(root.get("position").get("id"), lngPositionId));
            }
            if (intActive < 2) {
                predicates.add(cBuilder.equal(root.get("active"), intActive));
            }
            cQuery.select(root).where(predicates.toArray(new Predicate[] {}));

            TypedQuery<Employee> tQuery = entManager.createQuery(cQuery);
            employeesList = tQuery.getResultList();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        return employeesList;
    }
}

Я опускаю дополнительные DaoImp, поскольку они все имеют одинаковую структуру

Basi c Пример Кодовая проблема 1

EmployeeDaoImp employeesDao = new EmployeeDaoImp();
Employee employee = employeesDao.getById(1);
String newName = "Some Name";
boolean sameName = false;

if(employee != null){
    if(employee.getName().equals(newName)){ //SOMETIMES this throws the exception and debugging shows Name attribute to be null
        sameName = true;
    }
}

Basi c Пример Кодовая проблема 2

EmployeeDaoImp employeesDao = new EmployeeDaoImp();
employeesDao.addOrderBy("id", "desc");
List<Employee> employeesList = employeesDao.getList();
List<String> phoneList = new ArrayList<String>();

for (Employee employee : employeesList) {
    EmployeeDetail details = employee.getEmpDetails();

    phoneList.add(details.getPhone()); //SOMETIMES this throws null pointer exception, it is avoidable if I use the root.fetch as seen on EmployeeDaoImp file
}

Basi c Пример Кодовая проблема 4

String strNewName = request.getParameter("newName");
String strNewPhone = request.getParameter("newPhone");
long lngEmployeeId = Long.parseLong(request.getParameter("employeeId"));

EmployeeDaoImp employeeDao = new EmployeeDaoImp();
EmployeeDetailDaoImp employeeDetailDao = new EmployeeDetailDaoImp();
Employee employee = employeeDao.getById(lngEmployeeId);
employee.setName(strNewName);

boolean result = false;
if (employeeDao.saveOrUpdate(employee)) {
    EmployeeDetail details = employee.getEmpDetails();
    details.setPhone(strNewPhone);
    if(employeeDetailDao.saveOrUpdate(details)){ //SOMETIMES this throws null pointer exception regarding the parent(Employee)
        result = true;
    }
}

BaseDaoImp ​​& problem # 3 пример на openEntManager метод

public class BaseDaoImp <T, ID extends Serializable> {

    private static EntityManagerFactory emFactory;

    static {emFactory = Persistence.createEntityManagerFactory("com.daoImp");}

    protected static EntityManager entManager  = emFactory.createEntityManager();

    protected static EntityTransaction entTransaction = entManager.getTransaction();

    private List<String[]> orderBy = new ArrayList<String[]>();

    private List<String[]> conditions = new ArrayList<String[]>();

    private List<String> relations = new ArrayList<String>();


    /**
     * @brief BaseDaoImpl class constructor, manages a session in database
     */
    public BaseDaoImp() {
        if(!entManager.isOpen()) {
            entManager = emFactory.createEntityManager();
        }
    }
    .
    .
    .

    public void closeEntManager() {
        try {
            entManager.close();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public void openEntManager() {
        try {
            if(!entManager.isOpen()) {
                entManager = emFactory.createEntityManager();
            }
            entManager.clear(); //SOMETIMES this throws session closed error
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public void clearCache() {
        try {
            entManager.clear();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

Дополнительные примечания:

  1. Метод clearCache , который я использую только при успешном входе пользователя в систему для извлечения данных непосредственно из базы данных, а не кеша первого уровня
  2. Метод openEntManager просто для целей тестирования не используется.
  3. Это мой первый опыт работы с Spring / Hibernate, поэтому любые указания и критика приветствуются
  4. В базе данных для этой функции существуют все необходимые регистры правильной реализации, которая, очевидно, моя не является
  5. Извините, если мой engli sh или редактирование плохо

1 Ответ

0 голосов
/ 16 января 2020

Для задачи 1, хотя объект вашего сотрудника не является нулевым, но свойство "name" может иногда иметь значение null, тогда у null нет метода equals (), будет выдано исключение нулевого указателя

...