There is a structure. I want to link the three entities in this way: the Company should contain id, name of company and the list of Departments, each Department has a list of Workers, id and name of department. Each worker has name, id.
+Company
-int companyId
-String companyName
-Set<Department> listOfDepartments = new HashSet<Department>();
+Department
-int departmentId
-String departmentName
-Set<Worker> listOfWorkers = new HashSet<Worker>();
+Worker
-int workerId
-String workerName
My attempt:
Company
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#Entity
public class Company {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private int companyId;
private String companyName;
#XmlElementWrapper(name="listOfDepartments")
#XmlElement
#OneToMany(mappedBy = "company", cascade=CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Department> listOfDepartments = new HashSet<Department>();
public Set<Department> getListOfDepartments() {
return listOfDepartments;
}
public void setListOfDepartments(Set<Department> listOfDepartments) {
this.listOfDepartments = listOfDepartments;
}
public Company(){}
public Company(String companyName){
this.companyName = companyName;
}
#XmlAttribute(name="id")
public int getCompanyId() {
return companyId;
}
public void setCompanyId(int companyId) {
this.companyId = companyId;
}
#XmlElement(name="companyName")
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
Department
#Entity
public class Department {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private int idDepartment;
private String departmentName;
#XmlAttribute(name="companyId")
#ManyToOne()
#JoinColumn(name="companyId")
private Company company;
#XmlElementWrapper(name="listOfWorkers")
#XmlElement
#OneToMany(mappedBy = "department", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Worker> listOfWorkers = new HashSet<Worker>();
public Set<Worker> getListOfWorkers() {
return listOfWorkers;
}
public void setListOfWorkers(Set<Worker> listOfWorkers) {
this.listOfWorkers = listOfWorkers;
}
public Department(){}
public Department(String departmentName, Company company){
this.departmentName = departmentName;
this.company = company;
}
#XmlAttribute(name="id")
public int getIdDepartment() {
return idDepartment;
}
public void setIdDepartment(int idDepartment) {
this.idDepartment = idDepartment;
}
#XmlElement(name="departmentName")
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
Worker
#Entity
public class Worker {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private int idWorker;
private String workerName;
#ManyToOne
#JoinColumn(name="departmentId")
private Department department;
public Worker(){}
public Worker(String workerName,Department department){
this.workerName = workerName;
this.department = department;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
#XmlAttribute(name="id")
public int getIdWorker() {
return idWorker;
}
public void setIdWorker(int idWorker) {
this.idWorker = idWorker;
}
#XmlElement(name="name")
public String getWorkerName() {
return workerName;
}
public void setWorkerName(String workerName) {
this.workerName = workerName;
}
}
I catched the error:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
Class has two properties of the same name "companyId"
this problem is related to the following location:
at public int ru.eldarkaa.dto.Company.getCompanyId()
at ru.eldarkaa.dto.Company
this problem is related to the following location:
at private int ru.eldarkaa.dto.Company.companyId
at ru.eldarkaa.dto.Company
Class has two properties of the same name "companyName"
this problem is related to the following location:
at public java.lang.String ru.eldarkaa.dto.Company.getCompanyName()
at ru.eldarkaa.dto.Company
this problem is related to the following location:
at private java.lang.String ru.eldarkaa.dto.Company.companyName
at ru.eldarkaa.dto.Company
Class has two properties of the same name "listOfWorkers"
this problem is related to the following location:
at public java.util.Set ru.eldarkaa.dto.Department.getListOfWorkers()
at ru.eldarkaa.dto.Department
at private java.util.Set ru.eldarkaa.dto.Company.listOfDepartments
at ru.eldarkaa.dto.Company
this problem is related to the following location:
at private java.util.Set ru.eldarkaa.dto.Department.listOfWorkers
at ru.eldarkaa.dto.Department
at private java.util.Set ru.eldarkaa.dto.Company.listOfDepartments
at ru.eldarkaa.dto.Company
GODs of XML Annotations please advise me a solution.
By default JAXB treats public fields and properties as mapped. When you annotate a non-public field it causes that to become mapped as well resulting in the conflict.
Solutions
Annotate the property (get or set method) instead of the field (instance variable).
Annotate the field and the class with #XmlAccessorType(XmlAccessType.FIELD).
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
Related
I have the following scenario:
I have a Student class and students table.
I have Course class and courses table.
Every student and course have unique ID.
I would like to put a List into the Student class which is mapped by courses IDs.
I have tried a lot of annotations and relations but nothing succeeded
#Entity
#Table(name = "courses")
public class Course {
private long id;
private String name;
public Course() {
}
public Course(String name, int size) {
this.name = name;
this.size = size;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
#Table(name = "students")
public class Student {
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL)
private List<Course> courses = new ArrayList<>();
public Student() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
}
Can you help me hot to achieve that because i am a little newbie into the spring
Use the following when declaring one to many relation
#Column(name="course_id")
private Set<Course> courses;
You need to use OneToMany annotation.
#OneToMany(mappedBy = "students", cascade = CascadeType.ALL)
private List<Course> courses;
You need to give your list a type. For instance
List<Courses> courseList = new ArrayList<>();
I have 2 entity classes like below. After the parent object is persisted,
accessing the foreign key referenced object returns null.The entity classes are as below.
I have an Employee entity class like below
#Entity
#Table(name = "employees")
public class Employee {
private long employeeId;
private String name;
private long companyId;
private Company companyByCompanyId;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "employee_id")
public long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(long employeeId) {
this.employeeId = employeeId;
}
#Basic
#Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Basic
#Column(name = "company_id")
public long getCompanyId() {
return companyId;
}
public void setCompanyId(long companyId) {
this.companyId = companyId;
}
#ManyToOne
#JoinColumn(name = "company_id", referencedColumnName = "company_id", nullable = false, insertable = false, updatable = false)
public Company getCompanyByCompanyId() {
return companyByCompanyId;
}
public void setCompanyByCompanyId(Company companyByCompanyId) {
this.companyByCompanyId = companyByCompanyId;
}
}
and a Company entity class like below
#Entity
#Table(name = "companies")
public class Company {
private long companyId;
private String companyName;
private Collection<Employee> employeesByCompanyId;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "company_id")
public long getCompanyId() {
return companyId;
}
public void setCompanyId(long companyId) {
this.companyId;
}
#Basic
#Column(name = "company_name")
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
#OneToMany(mappedBy = "companyByCompanyId")
public Collection<Employee> getEmployeesByCompanyId() {
return employeesByCompanyId;
}
public void setEmployeesByCompanyId(Collection<Employee> employeesByCompanyId) {
this.employeesByCompanyId = employeesByCompanyId;
}
}
This is the controller method in a controller class
#ApiOperation(value="Create a new employee")
#ApiResponses({})
#RequestMapping(value= "/createEmployee",method= RequestMethod.POST)
public Callable<EmployeeDTO> createEmployee(
HttpServletRequest request,
#RequestBody #Valid final List<EmployeeDTO> employeeDto) {
long employeeId = employeeService.createEmployee(employeeDto);
EmployeeDTO createdEmployee = employeeService.getEmployee(employeeId);
return () -> createdEmployee;
}
This is the method for createEmployee(employeeDto) in the service class
#Transactional
public long createEmployee(employeeDto){
Employee employee = new Employee();
employee.setName(employeeDto.getName());
employee.setCompanyId(employeeDto.getCompanyId());
Employee savedEmployee = employeeRepository.save(employee);
return savedEmployee.getEmployeeId();
}
This is the getEmployee method in the same service class as above.
public EmployeeDTO getEmployee(long employeeId) {
Employee employee = employeeRepository.findByEmployeeId(employeeId);
EmployeeDTO employeeDTO = new EmployeeDTO();
employeeDTO.setEmployeeId(employee.getEmployeeId());
employeeDTO.setName(employee.getName());
employeeDTO.setCompanyByCompanyId(employee.getCompanyByCompanyId());
}
employee.getCompanyByCompanyId() -> this is where it throws the Null pointer exception.
The companies table already has the company row that I am associating with employee.
The jhipster doesn't support create many to many relationships with extra fields.
What is the best way to create many to many association with extra columns in jhispter? Should i create a two one-to-many relationship with extra fields?
Using JHipster Domain Language (JDL), a #ManytoMany holding extra properties (columns) can be easily achieved using an association entity and two ManyToOne relationships. See below:
entity Foo{
...
}
entity Bar{
...
}
entity FooBarAssociation{
extraProperty1 String
extraProperty2 String
...
}
relationship ManyToOne {
FooBarAssociation{foo} to Foo{bars}
FooBarAssociation{bar} to Bar{foos}
}
You will have to do it manually.
this post describes how: https://hellokoding.com/jpa-many-to-many-extra-columns-relationship-mapping-example-with-spring-boot-maven-and-mysql/
In general, as #Antares42 said, you should create an entity for the Many-To-Many table like so:
first entity:
#Entity
public class Book{
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Book() {
}
public Book(String name) {
this.name = name;
bookPublishers = new HashSet<>();
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
secound entity:
#Entity
public class Publisher {
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Publisher(){
}
public Publisher(String name){
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "publisher")
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
Join table entity:
#Entity
#Table(name = "book_publisher")
public class BookPublisher implements Serializable{
private Book book;
private Publisher publisher;
private Date publishedDate;
#Id
#ManyToOne
#JoinColumn(name = "book_id")
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
#Id
#ManyToOne
#JoinColumn(name = "publisher_id")
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
#Column(name = "published_date")
public Date getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(Date publishedDate) {
this.publishedDate = publishedDate;
}
}
This entity describes the relationship between Book and Publisher and the extra field is published_date
Let's say you have entities like Movie, Rater and needs a join table Ratings. You can write a JDL script like the following:
entity Movie { title String}
entity Rater { name String}
entity Rating { value Integer} //the extra field
relationship ManyToMany {
Rating{rater(name)} to Rater,
Rating{movie(title)} to Movie
}
save it in file.jdl in the project folder, open cmd type
jhipster import-jdl file.jdl
and you have everything
Exception with Spring. When I try to bind my entities to tables with #OneToMany annotation.
Caused by: org.hibernate.AnnotationException: #OneToOne or #ManyToOne
on com.wumf.iModuleSyncApps.impl.IAppEntity.packageName references an
unknown entity: java.lang.String at
org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:109)
at
org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1598)
at
org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1521)
at
org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1422)
at
org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:852)
... 41 more
#Entity
#Table(name = "IApp")
public class IAppEntity {
#ManyToOne
#JoinColumn(referencedColumnName="packageName")
#Id
private String packageName;
private String icon;
private String name;
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and
#Entity
#Table(name = "IAppsFriends")
public class IAppsFriends {
#GeneratedValue
#Id
private int id;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "packageName")
private List<IAppEntity> apps;
private String phone;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<IAppEntity> getApps() {
return apps;
}
public void setPackageName(List<IAppEntity> apps) {
this.apps = apps;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
Also I tried changing #JoinColumn(referencedColumnName="packageName") to
#JoinColumnn(name="packageName") to no avail.
Your #ManyToOne annotation is misplaced. You are annotating a String variable when you should be annotating a IAppsFriends:
#Table(name = "IApp")
public class IAppEntity {
#Id
private String packageName;
#ManyToOne
#JoinColumn(referencedColumnName="packageName")
private IAppsFriends friends;
// ... rest of code
}
You should also change IAppsFriends class to fix the mappedBy attribute:
#OneToMany(fetch = FetchType.EAGER, mappedBy = "friends")
private List<IAppEntity> apps;
If you want to add a OnwToMany relationship from IAppEntity to IAppsFriends, you should store the id of IAppsFriends in the table IApp. The type of IAppsFriends.id is int. So I think you should get a right join column like friends int(11) not null.
Then JPA will depend on the value of column friends to get the instance IAppsFriends.
#Table(name = "IApp")
public class IAppEntity {
#Id
private String packageName;
#ManyToOne
#JoinColumn(referencedColumnName="id")
private IAppsFriends friends;
// ... rest of code
}
PS: referencedColumnName means the reference in anther table. So the value should be id (the value of column friends should be one of the id of IAppsFriends)
Of course the code in IAppsFriends should modified to:
#OneToMany(fetch = FetchType.EAGER, mappedBy = "friends")
private List<IAppEntity> apps;
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.