долгое время браузер впервые спрашивает.
Я сталкиваюсь с несколькими проблемами с моим приложением, и я не знаю, есть ли у них что-то общее, меня поражает то, что они этого не делают происходит регулярно или по шаблону, иногда один объект иногда является другим, иногда один и тот же запрос, разделенный секундами, приводит к другому результату. Проблемы заключаются в следующем:
- Когда я получаю сущность, она приходит с некоторыми атрибутами правильными (id) и другими null , поэтому, когда я оцениваю, является ли сущность null возвращает false , но когда я пытаюсь работать с одним из атрибутов, он генерирует исключение нулевого указателя
- Когда я пытаюсь получить отношение, это возвращает ноль , это я решил путем извлечения отношения с запросом, но я не могу использовать это решение везде
- Иногда entityManager закрывается без каких-либо объяснений, я проверяю сеанс иначе открыть его, однако он оценивается как true, но в следующей строке кода, где я пытаюсь выполнить операцию, он выдает закрытый сеанс ошибка
- Иногда при сохранении дочернего объекта выдает исключение нулевого указателя на родительскую сущность
Замечания о моей реализации:
- Все отношения ленивые
- Нет Строка м у ethod есть какие-то отношения
- Я использую CriteriaBuilder для своих запросов
- Я использую EntityManager для сохранения своих сущностей
- Одна из моих ожидающих задач - сохранить изменения для нескольких сущностей в одной транзакции, поэтому в следующем коде это что-то, что я представляю
Сущность сотрудника
@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
}
}
}
Дополнительные примечания:
- Метод clearCache , который я использую только при успешном входе пользователя в систему для извлечения данных непосредственно из базы данных, а не кеша первого уровня
- Метод openEntManager просто для целей тестирования не используется.
- Это мой первый опыт работы с Spring / Hibernate, поэтому любые указания и критика приветствуются
- В базе данных для этой функции существуют все необходимые регистры правильной реализации, которая, очевидно, моя не является
- Извините, если мой engli sh или редактирование плохо