How to prevent record insertion in #ManyToOne hibernate mapping. Their Parent table have no record. We tried to insert record without parent table primary key and still the record was inserted into child table
Domain class
Department Table(Parent)
#Table(name = "Department")
#Entity
public class Department {
#Id
#GenericGenerator(name = "g1", strategy = "increment")
#GeneratedValue(generator = "g1")
private int deptno;
private String deptname;
private String depthead;
public Department() {
System.out.println("Department:0-param constuctor");
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
public String getDepthead() {
return depthead;
}
public void setDepthead(String depthead) {
this.depthead = depthead;
}
#Override
public String toString() {
return "Department [deptno=" + deptno + ", deptname=" + deptname +
", depthead=" + depthead + "]";
}
}
Emplyee table(child)
#Table(name = "EmpDetails")
#Entity
public class EmpDetails {
#Id
private int eno;
private String ename;
private double salary;
#ManyToOne(targetEntity = Department.class,
cascade = CascadeType.ALL,
fetch = FetchType.LAZY)
#JoinColumn(name = "deptno", referencedColumnName = "deptno")
private Department dept;
public EmpDetails() {
System.out.println("EmpDetails:0-param constructor");
}
public int getEno() {
return eno;
}
public void setEno(int eno) {
this.eno = eno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
#Override
public String toString() {
return "EmpDetails [eno=" + eno + ", ename=" + ename + ", salary=" +
salary + "]";
}
}
DAO
#Override
public void addEmployeesWithDept() {
// get Session
Session ses = HibernateUtil.getSession();
// create Department (parent)
//Department dept=new Department();
//dept.setDeptname("Accounts");
//dept.setDepthead("Jhon");
//create Employees(childs)
EmpDetails emp1 = new EmpDetails();
emp1.setEno(107);
emp1.setEname("raja");
emp1.setSalary(9000);
EmpDetails emp2 = new EmpDetails();
emp2.setEno(108);
emp2.setEname("ravi");
emp2.setSalary(8000);
// set childs to parent
//emp1.setDept(); emp2.setDept();
//Save objs
Transaction tx = null;
try {
tx = ses.beginTransaction();
ses.save(emp1);
ses.save(emp2);
tx.commit();
System.out.println(" Employees(childs) and associated parent objs are saved");
} catch (Exception e) {
tx.rollback();
}
}
Main Method
public static void main(String[] args) {
// Get DAO
M2ODAO dao=M2ODAOFactory.getDAOInstance();
//perform persitence operations
dao.addEmployeesWithDept();
//Close objs
HibernateUtil.closeSession();
HibernateUtil.closeSessionFactory();
}//main
Please find the below classes.
Main change: http://docs.oracle.com/javaee/6/api/javax/persistence/JoinColumn.html#nullable()
Specify below line: nullable = false
#JoinColumn(name = "deptno", referencedColumnName = "deptno", nullable = false)
which makes deptNo column as not null. Additionally specify deptNo as not null column so it avoids saving empdetails without dept number.
Or you can use: #NotNull on that field.
#NotNull
private Deparment dept;
Your model classes
Domain class
Department Table(Parent)
#Table(name = "Department")
#Entity
public class Department {
#Id
#GenericGenerator(name = "g1", strategy = "increment")
#GeneratedValue(generator = "g1")
private int deptno;
private String deptname;
private String depthead;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
private List<EmpDetails> empDetails = new ArrayList<EmpDetails>();
public Department() {
System.out.println("Department:0-param constuctor");
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
public String getDepthead() {
return depthead;
}
public void setDepthead(String depthead) {
this.depthead = depthead;
}
public List<EmpDetails> getEmpDetails() {
return empDetails;
}
public void setEmpDetails(List<EmpDetails> empDetails) {
this.empDetails = empDetails;
}
#Transient
public void addRoomAndBed(EmpDetails empDetails) {
if (getEmpDetails() == null) {
setRoomAndBeds(new ArrayList<EmpDetails>());
}
getEmpDetails().add(empDetails);
}
#Override
public String toString() {
return "Department [deptno=" + deptno + ", deptname=" + deptname +
", depthead=" + depthead + "]";
}
}
Emplyee table(child)
#Table(name = "EmpDetails")
#Entity
public class EmpDetails {
#Id
private int eno;
private String ename;
private double salary;
#ManyToOne(targetEntity = Department.class,cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "deptno", referencedColumnName = "deptno", nullable = false)
private Department dept;
public EmpDetails() {
System.out.println("EmpDetails:0-param constructor");
}
public int getEno() {
return eno;
}
public void setEno(int eno) {
this.eno = eno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
#Override
public String toString() {
return "EmpDetails [eno=" + eno + ", ename=" + ename + ", salary=" +
salary + "]";
}
}
Related
I have a manyToMany relationship between Department and Employee
Image of Employee schema
My problem came after i changed the composited keys to an Embeddable class and then calling that class as an Id on my DepartmentEmployee class
These are my classes:
DepartmentEmployeeId:
#Embeddable
public class DepartmentEmployeeId implements Serializable {
#Column(name = "dept_no")
private String deptNo;
#Column(name = "emp_no")
private Long empNo;
public DepartmentEmployeeId() {
}
public DepartmentEmployeeId(String deptNo, Long empNo) {
this.deptNo = deptNo;
this.empNo = empNo;
}
public String getDeptNo() {
return deptNo;
}
public void setDeptNo(String deptNo) {
this.deptNo = deptNo;
}
public Long getEmpNo() {
return empNo;
}
public void setEmpNo(Long empNo) {
this.empNo = empNo;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
DepartmentEmployeeId that = (DepartmentEmployeeId) o;
return Objects.equals(deptNo, that.deptNo) &&
Objects.equals(empNo, that.empNo);
}
#Override
public int hashCode() {
return Objects.hash(deptNo, empNo);
}
}
Department:
#Entity
#Table(name = "departments")
public class Department {
#Id
#Column(name = "dept_no")
private String deptNo;
#Column(name = "dept_name")
private String deptName;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "department", orphanRemoval = true)
#JsonIgnore
private List<DepartmentEmployee> departmentEmployees = new ArrayList<>();
public String getDeptNo() {
return deptNo;
}
public void setDeptNo(String deptNo) {
this.deptNo = deptNo;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public void addEmployee(DepartmentEmployee departmentEmployee) {
Employee employee=new Employee();
departmentEmployee = new DepartmentEmployee(this, employee);
departmentEmployees.add(departmentEmployee);
}
public List<DepartmentEmployee> getDepartmentEmployees() {
return departmentEmployees;
}
}
Employee:
#Entity
#Table(name = "employees")
public class Employee {
public enum Gender {M, F}
#Id
private Long empNo;
#Column(name = "birth_date")
private LocalDate birthDate;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Enumerated(EnumType.STRING)
#Column(name = "gender")
private Gender gender;
#Column(name = "hire_date")
private LocalDate hireDate;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "emp_no")
#JsonIgnore
private List<Salary> salaries = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "employee",orphanRemoval = true)
#JsonIgnore
private List<DepartmentEmployee> departmentEmployees = new ArrayList<>();
public List<Salary> getSalaries() {
return salaries;
}
public Long getEmpNo() {
return empNo;
}
public void setEmpNo(Long empNo) {
this.empNo = empNo;
}
public LocalDate getBirthDate() {
return birthDate;
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public LocalDate getHireDate() {
return hireDate;
}
public void setHireDate(LocalDate hireDate) {
this.hireDate = hireDate;
}
public void assignSalary(Salary salary) {
salaries.add(salary);
}
public List<DepartmentEmployee> getDepartmentEmployees() {
return departmentEmployees;
}
}
Department Employee
#Entity
#Table(name = "dept_emp")
public class DepartmentEmployee {
#EmbeddedId
private DepartmentEmployeeId id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("deptNo")
private Department department;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("empNo")
private Employee employee;
#Column(name = "from_date")
private LocalDate fromDate;
#Column(name = "to_date")
private LocalDate toDate;
public DepartmentEmployee() {
}
public DepartmentEmployee(Department department, Employee employee) {
this.department=department;
this.employee=employee;
this.id = new DepartmentEmployeeId(department.getDeptNo(), employee.getEmpNo());
}
public DepartmentEmployeeId getId() {
return id;
}
public void setId(DepartmentEmployeeId id) {
this.id = id;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public LocalDate getFromDate() {
return fromDate;
}
public void setFromDate(LocalDate fromDate) {
this.fromDate = fromDate;
}
public LocalDate getToDate() {
return toDate;
}
public void setToDate(LocalDate toDate) {
this.toDate = toDate;
}
}
My Service add method:
#Override
#Transactional
public Employee addEmployeeToDepartment(String deptNo, Long empNo, DepartmentEmployee departmentEmployee) {
Department department = this.departmentRepository.findById(deptNo).orElseThrow(() -> new DepartmentNotFoundException(deptNo));
Employee employee = this.employeeRepository.findById(empNo).orElseThrow(() -> new EmployeeNotFoundException(empNo));
departmentEmployee.setId(new DepartmentEmployeeId(department.getDeptNo(), employee.getEmpNo()));
departmentEmployee.setDepartment(department);
departmentEmployee.setEmployee(employee);
department.addEmployee(departmentEmployee);
this.departmentRepository.save(department);
return employee;
}
I found my problem, it was at this method:
public void addEmployee(DepartmentEmployee departmentEmployee) {
Employee employee=new Employee();
departmentEmployee = new DepartmentEmployee(this, employee);
departmentEmployees.add(departmentEmployee);
}
I was creating a new employee and i was not giving it an id, this is all i had to do:
public void addEmployee(DepartmentEmployee departmentEmployee) {
departmentEmployees.add(departmentEmployee);
}
Its very simple ...
In the Employee class you have
#Entity
#Table(name = "employees")
public class Employee {
public enum Gender {M, F}
#Id
//Add #GenerateValue here
private Long empNo;
You are missing a #GeneratedValue annotation just below the #Id.
For more details see here.
I have this error in spring boot:
attempted to assign id from null one-to-one property [com.endoorment.models.entity.ActionLang.action]
My code:
#Embeddable
public class ActionLangId implements Serializable {
private static final long serialVersionUID = 1 L;
#NotNull
#Column(name = "actions_id")
private Integer actionId;
#NotNull
#Column(name = "langs_id")
private Integer langId;
public ActionLangId() {}
public ActionLangId(Integer actionId, Integer langId) {
super();
this.actionId = actionId;
this.langId = langId;
}
public Integer getActionId() {
return actionId;
}
public void setActionId(Integer actionId) {
this.actionId = actionId;
}
public Integer getLangId() {
return langId;
}
public void setLangId(Integer langId) {
this.langId = langId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
ActionLangId that = (ActionLangId) o;
return Objects.equals(actionId, that.actionId) &&
Objects.equals(langId, that.langId);
}
#Override
public int hashCode() {
return Objects.hash(actionId, langId);
}
}
#Entity
#Table(name = "actions_langs")
public class ActionLang {
#EmbeddedId
private ActionLangId id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("actionId")
#JoinColumn(name = "actions_id")
private Action action;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("langId")
#JoinColumn(name = "langs_id")
private Lang lang;
#NotNull(message = "null")
#Size(max = 45, message = "short")
private String name;
public ActionLang() {}
public ActionLang(ActionLangId actionlangid, String name) {
this.id = actionlangid;
this.name = name;
}
public ActionLangId getId() {
return id;
}
public void setId(ActionLangId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "ActionLang [id=" + id + ", name=" + name + "]";
}
}
Service:
#Transactional
public ActionLang saveAction(Integer idlang, String name) {
Integer id = actionRepository.findActionId();
Action action = new Action(id);
actionRepository.save(action);
ActionLang actionlang = new ActionLang(new ActionLangId(id, idlang), name);
actionlangRepository.save(actionlang);
return actionlang;
}
Structure actionlang: {
"id": {
"actionId": 2,
"langId": 1
},
"name": "hkjhlhklhkllñkñl"
Thanks
My solution,
Entity Action:
#Entity
#Table(name = "actions")
public class Action {
#Id
private Integer id;
#OneToMany(mappedBy = "action")
private List<ActionLang> actionlang = new ArrayList<>();
public Action() { }
public Action(Integer id) {this.id = id;}
public Integer getId() {return id;}
public void setId(Integer id) {this.id = id;}
public List<ActionLang> getActionLang() {return actionlang;}
public void addActionLang(ActionLang actionlang) {
this.actionlang.add(actionlang);
}
public void removeActionLang(ActionLang actionlang) {
this.actionlang.remove(actionlang);
}
#Override
public String toString() {return "id: " + id ;}
}
Entity ActionLang,
#Entity
#Table(name = "actions_langs")
public class ActionLang {
#EmbeddedId
private ActionLangId id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("actionId")
#JoinColumn(name = "actions_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIgnore
private Action action;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("langId")
#JoinColumn(name = "langs_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIgnore
private Lang lang;
#NotNull(message="null")
#Size(max = 45, message="short")
private String name;
public ActionLang() {}
public ActionLang(ActionLangId actionlangid, String name) {
this.id = actionlangid;
this.name = name;
}
public ActionLangId getId() {return id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public void setId(ActionLangId id) {this.id = id;}
public Action getAction() {return action;}
public void setAction(Action action) {this.action = action;}
public Lang getLang() {return lang;}
public void setLang(Lang lang) { this.lang = lang; }
#Override
public String toString() {return "ActionLang [id=" + id + ", name=" + name + "]"; }
}
Service
#Component
public class ActionDAOService {
#Autowired
private IActionDao actionRepository;
#Autowired
private IActionLangDao actionlangRepository;
#Transactional
public Action saveAction(Integer idlang, String name){
Lang lang = new Lang();
lang.setId(idlang);
Integer id = actionRepository.findActionId();
if(id == null) {
id=(Integer) 1;
}
Action action = new Action(id);
actionRepository.save(action);
ActionLang actionlang = new ActionLang(new ActionLangId(id, idlang),name);
action.addActionLang(actionlang);
actionlang.setAction(action);
actionlang.setLang(lang);
actionlangRepository.save(actionlang);
return action;
}
}
I have modified service and I have the same error
#Transactional
public Action saveAction(Integer idlang, String name){
Integer id = actionRepository.findActionId();
if(id == null) {id=(Integer) 1;}
Action action = new Action(id);
ActionLang actionlang = new ActionLang(new ActionLangId(id, idlang),name);
action.getActionlang().add(actionlang);
actionRepository.save(action);
return action;
}
And the structure of action is this:
{
"id": 2,
"actionlang": [
{
"id": {
"actionId": 2,
"langId": 1
},
"name": "hkjhlhklhkllñkñl"
}
]
}
Entity action
#Entity
#Table(name = "actions")
public class Action {
#Id
private Integer id;
#OneToMany(mappedBy = "action", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ActionLang> actionlang = new ArrayList<>();
public Action() {
}
public Action(Integer id) {
super();
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<ActionLang> getActionlang() {
return actionlang;
}
#Override
public String toString() {
return "Action [id=" + id + ", actionlang=" + actionlang + ", getId()=" + getId() + ", getActionlang()="
+ getActionlang() + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()="
+ super.toString() + "]";
}
}
I have a RESTcontroller that has a delete mapping like so:
#DeleteMapping("/deleterequest/{custId}")
//#Transactional
public ResponseEntity<?> delete(#PathVariable long custId) {
log.info("entering deleterequest");
LeaveQuery deleteLeaveQuery = leaveQueryRepository.findOne(custId);
log.info("condition" + deleteLeaveQuery.getStatus().equals("Onbehandeld"));
// if (!deleteLeaveQuery.getStatus().equals("Onbehandeld"))
// return ResponseEntity.badRequest().build();
//deleteLeaveQuery.setAccount(null);
//leaveQueryRepository.save(deleteLeaveQuery);
log.info("is deleteLeaveQuery null? " + (deleteLeaveQuery == null));
//leaveQueryRepository.delete(deleteLeaveQuery);
//leaveQueryRepository.delete(deleteLeaveQuery.getId());
leaveQueryRepository.deleteById(deleteLeaveQuery.getId());
accountService.sendLeaveRequestCanceledNotification(deleteLeaveQuery);
return ResponseEntity.ok().build();
}
When I use the regular (built-in) delete function of my leaveQueryRepository, I get no error, not during log INFO mode nor with log DEBUG mode on. However the object doesn't get deleted either. Its still in the database after the delete method was called. When I make a custom spring repository method called deleteById I get the following error:
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call
at
I have no idea what is causing this error. The jparepository looks like this:
#Repository
public interface LeaveQueryRepository extends JpaRepository<LeaveQuery, Long> {
//#Modifying
public void deleteById(long id);
}
The LeaveRequest object looks like this:
#Entity
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id",
scope = LeaveQuery.class)
public class LeaveQuery implements Serializable {
#Id
#GeneratedValue
private Long id;
private Date startDate;
private Date endDate;
private String status = "Onbehandeld";
private String reason ="";
private int totalHours;
private String processedBy;
#ManyToOne(fetch = FetchType.EAGER) //, cascade = CascadeType.PERSIST
#JoinColumn(name = "FK_account", nullable = true)
private Account account;
public String getProcessedBy() {
return processedBy;
}
public void setProcessedBy(String processedBy) {
this.processedBy = processedBy;
}
public int getTotalHours() {
return totalHours;
}
public void setTotalHours(int totalHours) {
this.totalHours = totalHours;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Override
public String toString() {
return "LeaveQuery{" +
"id=" + id +
", startDate=" + startDate +
", endDate=" + endDate +
", denialReason='" + reason + '\'' +
'}';
}
}
It has a relation with an Account object which looks like this:
#Entity
//#JsonIgnoreProperties
//#JsonIdentityInfo(
// generator = ObjectIdGenerators.PropertyGenerator.class,
// property = "id",
// scope = Account.class)
public class Account implements Serializable {
#Id
#GeneratedValue
private Long id;
private String username;
private String password;
private String name;
private boolean admin;
private boolean enabled;
private int remainingStatutoryLeaveHours = 240;
private int remainingNonStatutoryLeaveHours = 60;
#JsonIgnore
#OneToMany(fetch = FetchType.EAGER, mappedBy = "account", cascade = CascadeType.ALL)
List<LeaveQuery> leaveQueryList;
//
#OneToMany(fetch = FetchType.LAZY, mappedBy = "account", cascade = CascadeType.ALL)
List<LaborPeriod> laborperiods = new ArrayList<>();
#OneToOne
private Person person;
#Enumerated
UserRole userRole = UserRole.USER;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public UserRole getUserRole() {
return userRole;
}
public void setUserRole(UserRole userRole) {
this.userRole = userRole;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public List<LaborPeriod> getLaborperiods() {
return laborperiods;
}
public void setLaborperiods(List<LaborPeriod> laborperiods) {
this.laborperiods = laborperiods;
}
public List<LeaveQuery> getLeaveQueryList() {
return leaveQueryList;
}
public void setLeaveQueryList(List<LeaveQuery> leaveQueryList) {
this.leaveQueryList = leaveQueryList;
}
public int getRemainingStatutoryLeaveHours() {
return remainingStatutoryLeaveHours;
}
public void setRemainingStatutoryLeaveHours(int remainingStatutoryLeaveHours) {
this.remainingStatutoryLeaveHours = remainingStatutoryLeaveHours;
}
public int getRemainingNonStatutoryLeaveHours() {
return remainingNonStatutoryLeaveHours;
}
public void setRemainingNonStatutoryLeaveHours(int remainingNonStatutoryLeaveHours) {
this.remainingNonStatutoryLeaveHours = remainingNonStatutoryLeaveHours;
}
#Override
public String toString() {
return "Account{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", admin=" + admin +
", enabled=" + enabled +
", remainingStatutoryLeaveHours=" + remainingStatutoryLeaveHours +
", remainingNonStatutoryLeaveHours=" + remainingNonStatutoryLeaveHours +
", userRole=" + userRole +
'}';
}
}
Does anyone know what could be causing this error?
Any help would be appreciated.
All controller methods should be none transactional.
You should add one more layer between Controller and Repository (Service layer) and put #Transactional on Service class or put this annotation on your method in this Service class.
It should be Controller -> Service -> Repository
To let #Transactional work you should init TransactionalManager.
You can add something like this in your Persistence Configuration
#Bean
public JpaTransactionManager transactionManager() throws IOException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
Use orphanRemoval = true.
Try to update your Account class like so
#JsonIgnore
#OneToMany(fetch = FetchType.EAGER, mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval = true)
List<LeaveQuery> leaveQueryList;
Also check out this question.
I have three entity classes, I have written the query which includes join of two tables.
Table: ExpensesCategories
#Entity
#Table(name = "ExpensesCategories")
public class ExpensesCategories {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "category_id", unique = true)
private int categoryId;
#NotNull
private String categoryName;
#NotNull
private String categoryCodeInBankStats;
public int getCategoryId() {
return categoryId;
}
public void setCategoryId(int categoryId) {
this.categoryId = categoryId;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getCategoryCodeInBankStats() {
return categoryCodeInBankStats;
}
public void setCategoryCodeInBankStats(String categoryCodeInBankStats) {
this.categoryCodeInBankStats = categoryCodeInBankStats;
}
}
Table: Transactions
#Entity
#Table(name = "TransactionHistory")
public class TransactionHistory {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Temporal(TemporalType.DATE)
private Date dateOfTransaction;
private String transactionType;
private String refNo;
private Date valueDate;
private double withdrawalAmount;
private double depositAmount;
private double closingBalance;
#ManyToOne
#JoinColumn(name="userDetailsId", referencedColumnName="user_id")
private UserDetails userDetails;
#ManyToOne
#JoinColumn(name="expenseCategoriesId", referencedColumnName="category_id")
private ExpensesCategories expenseCategories;
public TransactionHistory(int userId, Date dateOfTransaction, String transactionType, String refNo, Date valueDate,
double withdrawalAmount, double depositAmount, double closingBalance) {
this.dateOfTransaction = dateOfTransaction;
this.transactionType = transactionType;
this.refNo = refNo;
this.valueDate = valueDate;
this.withdrawalAmount = withdrawalAmount;
this.depositAmount = depositAmount;
this.closingBalance = closingBalance;
}
public TransactionHistory() {
}
public Date getDateOfTransaction() {
return dateOfTransaction;
}
public void setDateOfTransaction(Date date) {
this.dateOfTransaction = date;
}
public String getTransactionType() {
return transactionType;
}
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String refNo) {
this.refNo = refNo;
}
public Date getValueDate() {
return valueDate;
}
public void setValueDate(Date valueDate) {
this.valueDate = valueDate;
}
public double getWithdrawalAmount() {
return withdrawalAmount;
}
public void setWithdrawalAmount(double withdrawalAmount) {
this.withdrawalAmount = withdrawalAmount;
}
public double getDepositAmount() {
return depositAmount;
}
public void setDepositAmount(double depositAmount) {
this.depositAmount = depositAmount;
}
public double getClosingBalance() {
return closingBalance;
}
public void setClosingBalance(double closingBalance) {
this.closingBalance = closingBalance;
}
public UserDetails getUserDetails() {
return userDetails;
}
public void setUserDetails(UserDetails userDetails) {
this.userDetails = userDetails;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public ExpensesCategories getExpenseCategories() {
return expenseCategories;
}
public void setExpenseCategories(ExpensesCategories expenseCategories) {
this.expenseCategories = expenseCategories;
}
}
Table: User Details
#Entity
#Table(name = "Employee")
public class UserDetails {
#Id
#Column(name = "user_id", unique = true)
private int id;
#NotNull
private String firstname;
#NotNull
private String lastname;
#Column(unique = true)
#NotNull
private String emailaddress;
#NotNull
private String role;
public UserDetails(String firstname, String lastname, String emailaddress, String role) {
this.firstname = firstname;
this.lastname = lastname;
this.emailaddress = emailaddress;
this.role = role;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public UserDetails() {
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmailaddress() {
return emailaddress;
}
public void setEmailaddress(String emailaddress) {
this.emailaddress = emailaddress;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
#Override
public String toString() {
return "Employee [id=" + id + ", firstname=" + firstname + ", lastname=" + lastname + ", emailaddress="
+ emailaddress + ", role=" + role + "]";
}
I have written query like this in transaction entity.
#Query( nativeQuery=true, value="SELECT a.expense_categories_id, a.Total_withdrawal_Amount, b.category_code_in_bank_stats, b.category_name FROM (SELECT expense_categories_id , SUM(withdrawal_amount) AS Total_withdrawal_Amount FROM transaction_history GROUP BY expense_categories_id) a join expenses_categories b on a.expense_categories_id = b.category_id
")
List<Object[]> getCategorizedExpenses();
My Json Response is like:
[
[
1,
21,
"UPI",
"UPI Payments"
],
[
2,
3733.59,
"POS",
"Shopping"
]
]
But i want json response with column names as well:
[
[
expense_categories_id: 1,
Total_withdrawal_Amount: 21,
category_code_in_bank_stats: "UPI",
category_name: "UPI Payments"
],
[
expense_categories_id: 2,
Total_withdrawal_Amount: 3733.59,
category_code_in_bank_stats: "POS",
category_name: "Shopping"
]
]
Please help me out..
You would need to map the results directly to a POJO class and ad some json config:
1) Define the pojo
public ResultClass implements Serializable{
#JsonProperty("expense_categories_id")
private Integer expenseCategoriesId;
...
public ResultClass(Integer expenseCategoriesId ... // rest params){
this.expenseCategoriesId = expenseCategoriesId;
...
}
}
2) Define the mapping:
#SqlResultSetMapping(
name="myMapping",
classes={
#ConstructorResult(
targetClass=ResultClass.class,
columns={
#ColumnResult(name="expenseCategoriesId"),
#ColumnResult(name="totalWithdrawalAmount")
// further mappings ...
}
)
}
)
3) Define a native query
#NamedNativeQuery(name="TransactionHistory.myQuery"
, query="SELECT new mypackage.ResultClass(a.expense_categories_id as expeneCategoriesId ... ) from ...")
4) Define this method in the CrudRepository without the #Query annotation:
public List<ResultClass> myQuery();
Teh #SqlResultSetMapping and #NamedNativeQuery would need to be defined on one of your mapped entities.
Your native query will give you an object[][] as an result. So, it actually a mxn rows.
So,
I think you should create a class names Response
public class Response{
private Long expense_categories_id;
private Double Total_withdrawal_Amount;
private String category_code_in_bank_stats;
private String category_name;
//getters and setters for all attributes
}
List<Response> fillCategorizedExpenses(){
List<Response> response_List = new ArrayList<>();
Response response = null;
Object[][] // fill each object with by accessing their index from
//this array.
for() //iterate the object array. {
response = new Response();
response.setExpense_categories_id(value); // set all attributes.
....
....
....
response_List.add(response);
}
return response_List; //this will print as you need in your project.
}
Thank You :) Hope this might help you out.
Please help me in accessing Employee object in the below code using JAXB annotations. The application was developed in JPA SPRING. We are unable to access sub-object properties i.e, Employee properties
RESOURCE CORE FILE
#XmlAccessorType(XmlAccessType.PROPERTY)
#XmlRootElement(name="resource")
#Entity
#Table(name = "resource")
public class Resource implements java.io.Serializable {
private Integer resourceId;
private String resourceCode;
private String resourceName;
private String resourceNumber;
private Employee employee;
public Resource() {
}
public Resource(Employee employee,String resourceCode, String resourceName,
String resourceNumber
) {
this.employee = employee;
this.resourceCode = resourceCode;
this.resourceName = resourceName;
this.resourceNumber = resourceNumber;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "resource_id", unique = true, nullable = false)
public Integer getResourceId() {
return this.resourceId;
}
public void setResourceId(Integer resourceId) {
this.resourceId = resourceId;
}
#Column(name = "resource_code")
public String getResourceCode() {
return this.resourceCode;
}
public void setResourceCode(String resourceCode) {
this.resourceCode = resourceCode;
}
#Column(name = "resource_number")
public String getResourceNumber() {
return this.resourceNumber;
}
public void setResourceNumber(String resourceNumber) {
this.resourceNumber = resourceNumber;
}
#Column(name = "resource_name")
public String getResourceName() {
return this.resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "employee_id")
public Employee getEmployee() {
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
EMPLOYEE CORE FILE
#XmlAccessorType(XmlAccessType.PROPERTY)
#XmlRootElement(name="employee")
#Entity
#Table(name = "employee")
public class Employee implements java.io.Serializable {
private Integer employeeId;
private String employeeCode;
private String employeeName;
private List<Resource> resources = new ArrayList<Resource>(0);
public Employee() {
}
public Employee(String employeeCode, String employeeName,List<Resource> resources
) {
this.employeeCode = employeeCode;
this.employeeName = employeeName;
this.resources = resources;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "employee_id", unique = true, nullable = false)
public Integer getEmployeeId() {
return this.employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
#Column(name = "employee_code")
public String getEmployeeCode() {
return this.employeeCode;
}
public void setEmployeeCode(String employeeCode) {
this.employeeCode = employeeCode;
}
#Column(name = "employee_name")
public String getEmployeeName() {
return this.employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "employee")
public List<Resource> getResources() {
return this.resources;
}
public void setResources(List<Resource> resources) {
this.resources = resources;
}
}
You have to use the FetchType : Eager in RESOURCE CORE FILE of getEmployee() Method. Lazy fetch type is pulling only the parent object. Eager is pulling both.