Below is my code have one-to-many relation that is between parent and student.
My requirement is:
When I give a student's class_name then respective parents information should be display
If I enter reference id of parent to delete then respective child of that parent should deleted
i have left coding in test classes because i dont know how to write query to get out like example select operation. please let me know and if there is any error in DTO classes
select operation query:
select pt.P_MOBILE,pt.P_EMAIL,st.S_FIRSTNAME,st.REF_ID
from parent_info pt join student_info st on pt.REF_ID = st.REF_ID
where st.S_CLASS_TO_JOIN= ?;
Parent class:
#Table(name = "parent_info")
public class ParentDTO {
#Id
#GenericGenerator(name = "j", strategy = "increment")
#GeneratedValue(generator = "j")
#Column(name = "P_ID")
private int p_id;
#Column(name = "P_NAME")
private String p_name;
#Column(name = "P_PHONE")
private String p_phone;
#Column(name = "P_EMAIL")
private String p_email;
#Column(name = "REF_ID")
private String ref_id;
#OneToMany(cascade={CascadeType.ALL})
#JoinColumn(name="parent_id")
private List<StudentDTO> students;
//getters and setters
}
Student class:
#Table(name = "student_info")
public class StudentDTO {
#Id
#GenericGenerator(name = "j", strategy = "increment")
#GeneratedValue(generator = "j")
#Column(name = "S_ID")
private int s_id;
#Column(name = "S_NAME")
private String s_name;
#Column(name = "S_PHONE")
private String s_phone;
#Column(name = "S_EMAIL")
private String s_email;
#Column(name = "REF_ID")
private String ref_id;
#Column(name = "S_CLASS_NAME")
private String s_class_name;
#ManyToOne
#JoinColumn(name="parent_id")
private ParentDTO parent;
//getters and settrs
}
Test class to select query:
Tried this now: unexpected token: th near line 1, column 90 [select s from com.pradeepdemo.StudentDTO s join fetch s.parent where s.s_class_name = 10th]
public class Test {
public static void main(String[] args) {
Session session = null;
Transaction tx = null;
List<StudentDTO> groupList = null;
try {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
Query query = session.createQuery("select s from StudentDTO s join fetch s.parent where s.s_class_name = 10th");
groupList = query.list();
session.getTransaction().commit();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
session.close();
}
}
}
Test class to delete query:
public class Test {
public static void main(String[] args) {
Session session = null;
Transaction tx = null;
try {
SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
session.getTransaction().commit();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
session.close();
}
}
}
You can annotate your model classes with #Entity everything should sort itself out. Hibernate is supposed to work the basic CRUD operations on its own, without having to write HQL.
http://www.tutorialspoint.com/hibernate/hibernate_annotations.htm
Try to read examples on this link to have an idea about how to use HQL:
Hibernate - Query Language & Hibernate Query examples (HQL)
EDIT 1
As you can read in Docs : Forms of join syntax
HQL supports two forms of association joining: implicit and explicit.
Working Code
First Mapping between two entities like below
Parent
#Entity
#Table(name="PARENT")
public class ParentDTO {
#Id
#GeneratedValue
#Column(name="ID")
private Long parentId;
#Column(name="firstname")
private String parentName;
#Column(name="ParentPhone")
private Long parentPhone;
#Column(name="ParentEMail")
private String parentEMail;
#Column(name="ReferenceID")
private String referenceID;
#OneToOne(mappedBy="parent", cascade=CascadeType.ALL)
private Student student;
public ParentDTO() {
}
public ParentDTO(Long parentId, String parentName, Long parentPhone,
String parentEMail, String referenceID, Student student) {
super();
this.parentId = parentId;
this.parentName = parentName;
this.parentPhone = parentPhone;
this.parentEMail = parentEMail;
this.referenceID = referenceID;
this.student = student;
}
//getters and setters
}
Student
#Entity
#Table(name = "STUDENT")
public class StudentDTO {
#Id
#Column(name="ID", unique=true, nullable=false)
#GeneratedValue(generator="gen")
#GenericGenerator(name="gen", strategy="foreign", parameters=#Parameter(name="property", value="parent"))
private Long id;
#Column(name = "StudentName")
private String studentName;
#Column(name = "StudentClass")
private int studentClass;
#Column(name = "ReferenceID")
private String referenceID;
#OneToOne
#PrimaryKeyJoinColumn
private ParentDTO parent;
public Student() {
}
public Student(Long id, String studentName, int studentClass,
String referenceID, ParentDTO parent) {
super();
this.id = id;
this.studentName = studentName;
this.studentClass = studentClass;
this.referenceID = referenceID;
this.parent = parent;
}
//getters and setters
}
Select query
public void select()
{
Session session = null;
Transaction tx = null;
try {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
tx = session.beginTransaction();
String hql = "from ParentDTO as p, StudentDTO as s where p.referenceID=s.referenceID and s.referenceID='ReferencID-1'";
List<?> list = session.createQuery(hql).list();
for(int i=0; i<list.size(); i++) {
Object[] row = (Object[]) list.get(i);
ParentDTO parent = (ParentDTO)row[0];
Student student = (Student)row[1];
System.out.println(parent.getParentEMail());
System.out.println(student.getStudentName());
}
tx.commit();
} catch (HibernateException he) {
he.printStackTrace();
tx.rollback();
}
}
Related
I have two tables:
Employee
id
firstName
lastName
.
.
.
Training
id
employeeId
trainingName
trainingSuspsnseDate
trainingComplete
When I perform a standard SQL query in MySQL Workbench, it looks like this:
SELECT e.id, e.firstName, e.lastName, t.trainingName, t.trainingSuspenseDate, t.trainingComplete
FROM Employee e
JOIN Training t on t.employeeId = e.id
WHERE t.trainingSuspenseDate < CURDATE()
order by t.trainingSuspenseDate;
Now, I want to create a criteria query of the same SQL query, but I am having trouble with the join. This is what I have tried based on my googling:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> employeeQuery = builder.createQuery(Employee.class);
Root<Employee> employee = employeeQuery.from(Employee.class);
Join<Employee, Training> training = employee.join(Employee_.ID);
employeeQuery.select(builder.construct(Employee.class,
employee.get(Employee_.ID),
employee.get(Employee_.firstName),
employee.get(Employee_.lastName),
training.get(Training_trainingName),
training.get(Training_trainingSuspsnseDate),
training.get(Training_trainingComplete)));
However, I am getting the error:
incompatible types: inference variable Y has incompatible equality constraints Templates,Integer where Y,X are type-variables:
Y extends Object declared in method <Y>join(SingularAttribute<? super X,Y>)
X extends Object declared in interface From
I have tried other permutations of the JOIN, but I get different errors. I cannot seem to find the exact "secret" to creating this query.
Join<Employee, Training> training = training.join(Training_.employeeId);
or
Join<Employee, Training> training = training.join(Training_.employeeId).join(Employee_.ID);
or
Join<Training, Employee> training = training.join(Training_.employeeId);
or
Join<Training, Employee> training = training.join(Training_.employeeId).join(Employee_.ID);
or
.
.
.
EDIT: Added my model classes
Employee.java
#Entity
#Table(name = "employee")
#XmlRootElement
#NamedQueries(
{
#NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e"),
#NamedQuery(name = "Employee.deleteAll", query = "DELETE FROM Employee e"),
#NamedQuery(name = "Employee.countAll", query = "SELECT COUNT(e.ID) FROM Employee e")
})
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#GeneratedValue
#Column(name = "id")
private Integer ID;
#Basic(optional = true)
#Column(name = "name_first")
private String firstName;
#Basic(optional = true)
#Column(name = "name_last")
private String lastName;
#Basic(optional = true)
#Column(name = "created_date")
private String employeeDate;
#Basic(optional = true)
#Column(name = "personal_type")
private String personnelType;
public Employee() {
ID = 0;
}
public Employee(Integer id) {
this.ID = id;
}
public Integer getID() {
return ID;
}
public void setID(Integer id) {
this.ID = id;
}
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 getEmployeeDate() {
return employeeDate;
}
public void setEmployeeDate(String employeeDate) {
this.employeeDate = employeeDate;
}
public String getPersonnelType() {
return personnelType;
}
public void setPersonnelType(String personnelType) {
this.personnelType = personnelType;
}
}
Training.java
#Entity
#Table(name = "training")
#XmlRootElement
#NamedQueries(
{
#NamedQuery(name = "Training.findAll", query = "SELECT t FROM Training t"),
#NamedQuery(name = "Training.deleteAll", query = "DELETE FROM Training t"),
#NamedQuery(name = "Training.countAll", query = "SELECT COUNT(t.ID) FROM Training t")
})
public class Training implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#GeneratedValue
#Column(name = "ID")
private Integer ID;
#Basic(optional = false)
#Column(name = "employee_id")
private String employeeId;
#Basic(optional = false)
#Column(name = "training_name")
private String trainingName;
#Basic(optional = false)
#Column(name = "training_suspense_date")
private Date trainingSuspenseDate;
#Basic(optional = false)
#Column(name = "training_complete")
private Boolean trainingComplete;
public Integer getID() {
return ID;
}
public void setID(Integer ID) {
this.ID = ID;
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public void setTrainingName(String trainingName) {
this.trainingName = trainingName;
}
public String getTrainingName() {
return trainingName;
}
public void setTrainingSuspenseDate(Date trainingSuspsenseDate) {
this.trainingSuspsenseDate = trainingSuspsenseDate;
}
public Date getTrainingSuspenseDate() {
return trainingSuspsenseDate;
}
public void setTrainingComplete(Boolean trainingComplete) {
this.trainingComplete = trainingComplete;
}
public Boolean getTrainingComplete() {
return trainingComplete;
}
}
I can figure out that You have a meta-model generated for your query.
So the best way will be to extends your entity definition as follow:
You have to add mapping in your Training class:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "employeeId")
private Employee employee;
Then in your Employee class add oposite reference:
#OneToMany(mappedBy = "employee")
private Set<Training> trainings = new HashSet<>();
Then change your criteria query to:
Join<Employee, Training> training = employee.join(Employee_.trainings);
You can try cross join. Native sql is a bit differerent but the result is as axpected
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> employeeQuery = builder.createQuery(Employee.class);
Root<Employee> employee = employeeQuery.from(Employee.class);
Root<Employee> training= employeeQuery.from(Training.class);
employeeQuery.select(builder.construct(Employee.class,
employee.get(Employee_.ID),
employee.get(Employee_.firstName),
employee.get(Employee_.lastName),
training.get(Training_.trainingName),
training.get(Training_.trainingSuspsnseDate),
training.get(Training_.trainingComplete)))
.where(builder.equal(employee.get(Employee_.ID), training.get(Training_.employeeId)));
Looking at your model classes, the entities are not related directly (even though the employeeId in Training is supposed to be a foreign key, it is not defined as such in the entity relationship. So, if you wish to work with the existing entities, without changing them, you would need the following -
A POJO (for example EmpRes) which maps the attributes as per the select clause. criteriaQuery should be initialized on this POJO as -
CriteriaQuery<EmpRes> criteriaQuery = builder
.createQuery(EmpRes.class);
As the entities are unrelated, the generated query will have a cross join.
The code would look like -
criteriaQuery.select(builder.construct(EmpRes.class, employee
.get(Employee_.getAttribute("ID").getName()), employee
.get(Employee_.getAttribute("firstName").getName()), employee
.get(Employee_.getAttribute("lastName").getName()), training
.get(Training_.getAttribute("trainingName").getName()),
training.get(Training_.getAttribute("trainingSuspenseDate")
.getName()), training.get(Training_.getAttribute(
"trainingComplete").getName())));
criteriaQuery.where(builder.equal(employee.get("ID"), training.get("employeeId")));
List<EmpRes> employees = entityManager.createQuery(criteriaQuery).getResultList();
However, if the entities can be changed (as should be the ideal design), an Employee has Training(s). So, a #OneToMany relationship between Employee and Training model classes should be defined as follows -
Employee.java
#OneToMany(mappedBy="employee")
private Set<Training> trainings = new HashSet<>();
Training.java
#ManyToOne
#JoinColumn(name = "employeeId")
private Employee employee;
CriteriaQuery related code -
Join<Employee, Training> trainingJoin = employee.join(Employee_.getAttribute("trainings").getName());
criteriaQuery.select(builder.construct(EmpRes.class, employee
.get(Employee_.getAttribute("ID").getName()), employee
.get(Employee_.getAttribute("firstName").getName()), employee
.get(Employee_.getAttribute("lastName").getName()),
trainingJoin.get(Training_.getAttribute("trainingName")
.getName()), trainingJoin.get(Training_.getAttribute(
"trainingSuspenseDate").getName()), trainingJoin
.get(Training_.getAttribute("trainingComplete")
.getName())));
You can then add the additional where clause based on your requirements.
A good reference to Criteria API is here.
This error message - incompatible types: inference variable Y has incompatible equality constraints - is an indication you need to carefully review DATA TYPES of the columns you are joining. The should be same data types on both sides of the = for performance and high speed comparisons.
I have two Entities, TableA and TableB, with a many-to-many mapping between them. When I try to select all of table_b using a createNativeQuery I am able to get all table_b's data but I'm not able to reference any of table_a's data.
table_a entity
#Entity
#Table(name = "table_a")
public class TableA implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name = "data1")
private String data1;
#Column(name = "data2")
private String data2;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "a_b_mapping",
joinColumns = #JoinColumn(name = "a_id"),
inverseJoinColumns = #JoinColumn(name = "b_id"))
private List<TableB> bItems;
// getters/setters
public List<TableB> getBItems() {
if (bItems == null) { bItems = new ArrayList<>(); }
return bItems;
}
public void setBItems(List<TableB> bItems) {
this.bItems = bItems;
}
}
table_b entity
#Entity
#Table(name = "table_b")
public class TableB implements Serializable {
#Id
#Column(name = "id")
private Integer id;
#ManyToMany(mappedBy = "bItems")
private List<TableA> aItems;
// Getters/Setters
public List<TableA> getAItems() {
if (aItems == null) { aItems = new ArrayList<>(); }
return aItems;
}
public void setAItems(List<TableA> aItems) {
this.aItems = aItems;
}
}
NOTE: I'm setting the id manually for TableB before inserting
Processor:
#Component
public class ProcessorDAO {
#PersistenceUnit
private EntityManagerFactory entityManagerFactory;
#Transactional
public void process() {
EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction entityTransaction = em.getTransaction();
try {
entityTransaction.begin();
Query q = em.createNativeQuery("SELECT * FROM table_b", TableB.class);
List<TableB> tableBItems = q.getResultList();
for (TableB item : tableBItems) {
// Always 0 here?
item.getAItems().size();
}
entityTransaction.commit();
} catch (RuntimeException e) {
if (entityTransaction.isActive()) {
entityTransaction.rollback();
}
throw e;
} finally {
em.close();
}
}
}
I'm able to get AItems if I use findAll from TableB's repository but I was trying to get this to work with just the entity manager, not sure what the difference is.
In your case, the foreign key is actually in Table A, selecting only table B, it’s not possible to get the association. You need to join to to table A in the native sql.
Select * from tableB
Join tableA .....
I have a category table.In which first 5 are main category and
others are sub category.
I need to fetch the sub categories of first 5 main category so i have found the sql query
SELECT m.category_id,m.category_name AS 'Parent',
e.category_name AS 'Sub'
FROM category e
INNER JOIN category m ON m.category_id = e.parent_category_id
ORDER BY Parent
The query is joining the same table itself.and am getting the result given below
Result
How can i convert the SQL query to HQL and return the data like above image to user in
standard json format ?
FetchSubCategory
import java.io.Serializable;
import java.util.Set;
import javax.persistence.*;
#Entity
#Table(name = "category")
public class FetchSubCategory implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "category_id")
private Integer categoryId;
#Column(name = "category_name")
private String categoryName;
#ManyToOne(cascade = {CascadeType.ALL})
#JoinColumn(name = "parent_category_id")
private FetchSubCategory parent;
#OneToMany(mappedBy = "parent")
private Set<FetchSubCategory> subCategory;
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public FetchSubCategory getParent() {
return parent;
}
public void setParent(FetchSubCategory parent) {
this.parent = parent;
}
public Set<FetchSubCategory> getSubCategory() {
return subCategory;
}
public void setSubCategory(Set<FetchSubCategory> subCategory) {
this.subCategory = subCategory;
}
}
Method
public Set<FetchSubCategory> fetchSubCategory() throws SQLException, ClassNotFoundException, IOException {
Set<FetchSubCategory> groupList = null;
try {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("SELECT m.categoryName AS 'Parent', e.categoryName AS 'Sub' FROM FetchSubCategory e INNER JOIN FetchSubCategory m ORDER BY Parent");
groupList = (Set<FetchSubCategory>) query.list();
} catch (Exception e) {
e.printStackTrace();
}
return groupList;
}
Can any one please correct my mistake and tell me how to fetch result like above image?
This stuff will solve your problem
#Entity
#Table(name = "category")
public class FetchSubCategory implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "category_id")
private Integer categoryId;
#Column(name = "category_name")
private String categoryName;
#NotFound(action = NotFoundAction.IGNORE)
#ManyToOne
#JsonIgnore
#JoinColumn(name = "parent_category_id")
private FetchSubCategory mainCategory;
#JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)//Avoiding empty json arrays.objects
#OneToMany(mappedBy = "mainCategory", fetch = FetchType.EAGER)
private List<FetchSubCategory> subCategory;
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public FetchSubCategory getMainCategory() {
return mainCategory;
}
public void setMainCategory(FetchSubCategory mainCategory) {
this.mainCategory = mainCategory;
}
public List<FetchSubCategory> getSubCategory() {
return subCategory;
}
public void setSubCategory(List<FetchSubCategory> subCategory) {
this.subCategory = subCategory;
}
Get your sub categories
public List<FetchSubCategory> fetchSubCategory() throws SQLException, ClassNotFoundException, IOException {
List<FetchSubCategory> groupList = null;
try {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("select distinct e FROM FetchSubCategory e INNER JOIN e.subCategory m ORDER BY m.mainCategory");
groupList = query.list();
} catch (Exception e) {
e.printStackTrace();
}
return groupList;
}
For self join as in your case, below will work for you.
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name = "parent_category_id")
private FetchSubCategory parent;
#OneToMany(mappedBy = "parent")
private Set<FetchSubCategory> subCategory;
FetchSubCategory entity class, we defined two attributes: FetchSubCategory parent and Set<FetchSubCategory> subCategory. Attribute parent is mapped with #ManyToOne annotation and subordinates is mapped with #OneToMany. Also within #OneToMany attribute we defined mappedBy="parent" making parent as the relationship owner and thus which manages the foreign relationship within table.
Also the annotation #JoinColumn is defined on parent making it the relationship owner. #JoinColumn defines the joining column which in our case is parent_category_id.
I am using hibernate and getting data from two tables.
I create two Entity classes User.java and Profession.java to fetch data from the tables user_table and user_profession.
user_table contains user information and user_profession contains the profession of user with uid as a foreign key. I am getting one record from user_table and getting the profession of that user from user_profession
Here is User.java
#Entity
#Table(name="user_table")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name="id")
private long id;
#Column(name="full_name")
private String fullName;
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="u_id")
private List<Profession> prof;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<Profession> getProf() {
return prof;
}
public void setProf(List<Profession> prof) {
this.prof = prof;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
}
I used #OneToMany annotation here to connect with Profession.java because i want to get the profession of user
. Now i got the profession of user but now i want those records from profession table whichs contains same profession as i fetched before.
Here is my Profession.java
#Entity
#Table(name="user_profession")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Profession implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name="id")
private long id;
#Column(name="u_id")
private long uid;
#Column(name="profession")
private String profession;
#Column(name="type")
private String professionType;
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="u_id")
private List<User> prof;
//Getters and setters
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getUid() {
return uid;
}
public void setUid(long uid) {
this.uid = uid;
}
public String getProfession() {
return profession;
}
public void setProfession(String profession) {
this.profession = profession;
}
public String getProfessionType() {
return professionType;
}
public void setProfessionType(String professionType) {
this.professionType = professionType;
}
}
Here is my Dao class
#Autowired
SessionFactory sessionFactory;
Session session = null;
Transaction tx = null;
#SuppressWarnings({ "unchecked", "rawtypes" })
public List<User> getUserById(long id) throws Exception {
session = sessionFactory.openSession();
Criteria cr = session.createCriteria(User.class);
cr.add(Restrictions.eq("id", id));
List results = cr.list();
tx = session.getTransaction();
session.beginTransaction();
tx.commit();
return results;
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public List<Profession> getProfessionById(long id) throws Exception {
session = sessionFactory.openSession();
Criteria cr = session.createCriteria(Profession.class);
cr.add(Restrictions.eq("u_id", id));
List results = cr.list();
tx = session.getTransaction();
session.beginTransaction();
tx.commit();
return results;
}
Here is my Controller
#Autowired
SubscribeDataService subscribeService;
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public #ResponseBody
List<User> getSubscriber(#PathVariable("id") long id) {
List<User> user = null;
try {
user = subscribeService.getUserById(id);
} catch (Exception e) {
e.printStackTrace();
}
return user;
}
Here is your User class :
#Entity
#Table(name="user_table")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name="id")
private long id;
#Column(name="full_name")
private String fullName;
#OneToMany(cascade=CascadeType.REMOVE, fetch=FetchType.LAZY)
private Set<Profession> prof;
// getters and setters
}
here is profession class
#Entity
#Table(name="user_profession")
// i have no idea why you need such JSONIgnore, but ok
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Profession implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name="id")
private long id;
#Column(name="u_id")
private long uid;
#Column(name="profession")
private String profession;
#Column(name="type")
private String professionType;
#ManyToOne
#JoinColumn(name = "userid", nullable = false)
private User usersProfession
// getters and metters
}
Now comes you DAO class :
private final SessionFactory sessionFactory;
#Autowired
public DAOClasname(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// I am presuming you want user and passing user id.
// Don't just throw Exception, use something meaningful
public User getUserById(long id){
Session session = this.sessionFactory.getCurrentSession();
return (User)session.get(User.class,id);
}
// I am presuming you are passing user id and expect users profession
// Don't just throw Exception, use something meaningful
public List<Profession> getProfessionById(long id){
Session session = this.sessionFactory.getCurrentSession();
org.hibernate.Query query = session.createQuery("from Profession as P where p.usersProfession.userId=:id");
query.setParameter("id",id);
return query.list();
}
For DAO class, please use interface, and your DAOImpl class should implement these methods in DAOImpl class. If anyone can suggest corrections, those are welcome.
I have been looking the forums and everywhere for a unidirectional manyToMany query. I find many examples but i can't really adjust them to my needs :(
I have 2 entity classes (Anime & User)
Anime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "anime_id")
private Integer id;
//Other fields etc.
}
User {
#Id
#ValidUsername
#Column(name = "user_id")
private String username;
#ManyToMany()
#JoinTable(name = "users_animes",
joinColumns = #JoinColumn(name = "anime_id", referencedColumnName = "anime_id"),
inverseJoinColumns = #JoinColumn(name = "user_id", referencedColumnName = "user_id"))
private final List<Anime> animes = new ArrayList<>();
}
Anime simply holds the data from the anime.
User holds the username etc of the user and a list of anime that he subscribed to.
Now i'm trying to find a query that will let me get all the animes in that list.
It's mapped in a table as "users_animes".
Would be a huge help since i'm fairly new to JPQL.
Thanks!
Here's a simple example. Let's assume that we have Country Entity, which can have multiple Citizens:
#Entity
#Table (name = "countries")
public class Country implements Serializable {
#Id
#Column (name = "coun_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column (name = "country_name")
private String countryName;
#ManyToMany (cascade = CascadeType.ALL)
#JoinTable (
name = "citizen_country",
joinColumns = #JoinColumn (name = "country_id", referencedColumnName = "coun_id"),
inverseJoinColumns = #JoinColumn (name = "citizen_id", referencedColumnName = "cit_id")
)
private List<Citizen> citizens;
public Country() {}
public Country(String countryName) {
this.countryName = countryName;
}
//getters and setters
}
And Citizen, which can belong to multiple Countries:
#Entity
#Table (name = "citizens")
public class Citizen implements Serializable {
#Id
#Column (name = "cit_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column (name = "country_name")
private String citizenName;
public Citizen() {}
public Citizen(String citizenName) {
this.citizenName = citizenName;
}
public void setId(Long id) { this.id = id; }
public Long getId() { return id; }
public void setCitizenName(String citizenName) { this.citizenName = citizenName; }
public String getCitizenName() { return citizenName; }
//getters and setters
}
It's unidirectional, just as you wanted it to be. Therefore, Citizen Entity is unaware of Country, so you can't get directly information to which Country a certain Citizen belongs. However, you can retrieve info about which Citizens belong to a certain Country.
Going further, you can populate your tables:
Citizen citizen1 = new Citizen("Smith");
Citizen citizen2 = new Citizen("Kowalski");
Citizen citizen3 = new Citizen("Muller");
dataAccess.saveCitizen(citizen1);
dataAccess.saveCitizen(citizen2);
dataAccess.saveCitizen(citizen3);
// now let's fetch them from DB, along with their other properties (only id in this case)
citizen1 = dataAccess.getCitizenByName("Smith");
citizen2 = dataAccess.getCitizenByName("Kowalski");
citizen3 = dataAccess.getCitizenByName("Muller");
Country country1 = new Country("Foo");
Country country2 = new Country("Bar");
// create lists to hold citizens for each country
List<Citizen> citizenList1 = new ArrayList();
List<Citizen> citizenList2 = new ArrayList();
// add elements to the lists
citizenList1.add(citizen1);
citizenList1.add(citizen2);
citizenList2.add(citizen2);
citizenList2.add(citizen3);
//assign lists of citizens to each country
country1.setCitizens(citizenList1);
country2.setCitizens(citizenList2);
//save data in DB
dataAccess.saveCountry(country1);
dataAccess.saveCountry(country2);
//fetch list of all persisted countries (associated Citizens will come along)
countries = dataAccess.getAllCountries();
And finally:
#Stateless
public class DataAccess {
#PersistenceContext
EntityManager em;
public void saveCountry(Country country) {
em.persist(country);
}
public void saveCitizen(Citizen citizen) {
em.persist(citizen);
}
public Citizen getCitizenByName(String name) {
Query query = em.createQuery("SELECT c FROM Citizen c WHERE c.citizenName = :name");
query.setParameter("name", name);
return (Citizen) query.getSingleResult();
}
public List<Country> getAllCountries() {
Query query = em.createQuery("SELECT c FROM Country c");
return (List<Country>) query.getResultList();
}
}