I have User and Employee tables on MySQL, and there is employeeId as foreign key in User table.
Now I need to get Employees who do not have User.
I write this SQL in MySQL Workbench, this works exactly how I want:
SELECT * FROM HUMANRESOURCE.EMPLOYEE E LEFT JOIN AUTHORIZE.USER U
ON U.EMPLOYEEOBJID = E.OBJID
WHERE U.EMPLOYEEOBJID is NULL;
But when I try to implement this SQL as JPA query, it returns nothing. Here is JPA Query:
Query query = em.createQuery("SELECT e FROM Employee e LEFT JOIN User u
WHERE u.employee.objid = e.objid
AND u.employee IS NULL");
And here is truely working JPA Query that I use for getting Employees who have user:
Query query = em.createQuery("SELECT e FROM Employee e INNER JOIN User u
WHERE u.employee.objid = e.objid");
What am I doing wrong here?
Update for entity classes:
Base.java
package com.kadir.entity;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Date;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
#Cacheable
#MappedSuperclass
public abstract class Base {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "OBJID")
private BigInteger objid;
#Column(name = "CREATEDBY")
private String createdby;
#Column(name = "CREATEDDATE")
private Timestamp createddate;
#Version
#Column(name = "ROWVERSION")
private Integer rowversion;
#Column(name = "UPDATEDBY")
private String updatedby;
#Column(name = "UPDATEDDATE")
private Timestamp updateddate;
#Column(name = "ARCHIVED", columnDefinition = "int default 0")
private int archived;
public BigInteger getObjid() {
return this.objid;
}
public void setObjid(BigInteger objid) {
this.objid = objid;
}
public String getCreatedby() {
return this.createdby;
}
public void setCreatedby(String createdby) {
this.createdby = createdby;
}
public Date getCreateddate() {
return this.createddate;
}
public void setCreateddate(Timestamp createddate) {
this.createddate = createddate;
}
public Integer getRowversion() {
return this.rowversion;
}
public void setRowversion(Integer rowversion) {
this.rowversion = rowversion;
}
public String getUpdatedby() {
return this.updatedby;
}
public void setUpdatedby(String updatedby) {
this.updatedby = updatedby;
}
public Timestamp getUpdateddate() {
return this.updateddate;
}
public void setUpdateddate(Timestamp updateddate) {
this.updateddate = updateddate;
}
public int getArchived() {
return archived;
}
public void setArchived(int archived) {
this.archived = archived;
}
}
Employee.java
package com.kadir.entity.humanresource;
import com.kadir.entity.corporation.Company;
import com.kadir.entity.Base;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the EMPLOYEE database table.
*
*/
#Cacheable
#Entity
#Table(name = "EMPLOYEE", schema = "HUMANRESOURCE")
#NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e")
public class Employee extends Base implements Serializable {
private static final long serialVersionUID = 1L;
#ManyToOne
#JoinColumn(name = "COMPANYOBJID")
private Company company;
#Column(name = "FIRSTNAME")
private String firstname;
#Column(name = "GENDER")
private int gender;
#Column(name = "EMAIL")
private String email;
#Column(name = "PHONE")
private String phone;
#Column(name = "LASTNAME")
private String lastname;
public Employee() {
}
public Company getCompany() {
return this.company;
}
public void setCompany(Company company) {
this.company = company;
}
public String getFirstname() {
return this.firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public int getGender() {
return this.gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return this.phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getLastname() {
return this.lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
}
User.java
package com.kadir.entity.authorize;
import com.kadir.entity.Employee;
import com.kadir.entity.Base;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the USER database table.
*
*/
#Cacheable
#Entity
#Table(name="USER", schema="AUTHORIZE")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User extends Base implements Serializable {
private static final long serialVersionUID = 1L;
#OneToOne
#JoinColumn(name="EMPLOYEEOBJID")
private Employee employee;
#Column(name="NAME")
private String name;
#Column(name="PASSWORD")
private String password;
public User() {
}
public Employee getEmployee() {
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
EclipseLink has support for the ON clause, so try using
"SELECT e FROM Employee e LEFT JOIN User u on u.employee = e WHERE u.employee IS NULL"
You can also use exist and a subquery:
"select e from Employee e where not exists (select 1 from User u where u.employee = e)"
In my case, I'm using Apache OpenJPA.
Query should be something like this:
SELECT e FROM Employee e LEFT JOIN e.user u WHERE u.employeeId IS NULL
I had similar error. I had conditional OneToOne relation. I fixed problem like that.
#Query("SELECT e FROM Employee e LEFT OUTER JOIN User u ON u = e.user " +
"WHERE (u IS NULL OR e.condition = :conditionValue) ")
Related
I am trying to perform join in hibernate and i am using struts2.
I am working with hibernate using annotaions. Now i am unable to perform join between two tables.My first table is "studentprojects" which contain pid and email.Second table is "initialprojectdetials" which contains pid,name,description... similarly some other fields.I have to get the data of second table by performing join around pid of first table.
For this am using this query:
String hql="from InitialProjectDTO I join I.projectId S where I.projectId=:id";
Query query=session.createQuery(hql);
query.setParameter("id", id);
mail =query.list();
where mail is the arraylist of InitialProjectDTO.
And my InitialProjectDTO is:
package edu.pma.dto;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="initialprojectdetail")
public class InitialProjectDTO {
#Id
#Column(name="projectId")
#OneToMany(cascade=CascadeType.ALL)
#JoinTable(name="studentprojects",joinColumns=#JoinColumn(name="projectId"))
int projectId;
#Column(name="name")
String name;
#Column(name="description")
String description;
#Column(name="technology")
String technology;
#Column(name="guide")
String guide;
#Column(name="duration")
int duration;
#Column(name="status")
String status;
#Column(name="report")
String report;
public String getReport() {
return report;
}
public void setReport(String report) {
this.report = report;
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTechnology() {
return technology;
}
public void setTechnology(String technology) {
this.technology = technology;
}
public String getGuide() {
return guide;
}
public void setGuide(String guide) {
this.guide = guide;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
my SudentProjectDTO is:
package edu.pma.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="studentprojects")
public class StudentProjectDTO {
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
#Id
#Column(name="email")
String email;
#Column(name="projectId")
int projectId;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
This is the error which i am getting:
Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: edu.pma.dto.InitialProjectDTO.projectId
Method "execute" failed for object edu.pma.actions.LoginAction#1096a56
File: org/hibernate/cfg/annotations/CollectionBinder.java
You should try to use different models
#Entity
public class InitialProjectDTO {
#OneToMany(mappedBy = "project")
private Collection<StudentProjectDTO> students;
}
#Entity
public class StudentProjectDTO {
#ManyToOne
private InitialProjectDTO project;
}
And with the proper model it shuld be easy to write hql, you might want to look here for examples https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html.
Also I would suggest to look here for example of models. http://viralpatel.net/blogs/hibernate-one-to-many-annotation-tutorial/
See following example might its help to you
#Entity
#Table(name="initialprojectdetail")
public class InitialProjectDTO {
private Integer initialProjectDTOId;
private Set<StudentProjectDTO > studentProjectDTO = new HashSet<StudentProjectDTO >(0);
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "initial_projectDTO_id", unique = true, nullable = false)
public Integer getInitialProjectDTOId() {
return this.initialProjectDTOId;
}
public void setInitialProjectDTOId(Integer initialProjectDTOId) {
this.initialProjectDTOId = initialProjectDTOId;
}
#OneToMany(mappedBy = "studentprojects", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Set<StudentProjectDTO> getUserRole() {
return this.studentProjectDTO;
}
public void setUserRole(Set<StudentProjectDTO> studentProjectDTO) {
this.studentProjectDTO = studentProjectDTO;
}
}
#Entity
#Table(name="studentprojects")
public class StudentProjectDTO {
private InitialProjectDTO project;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "initial_projectDTO_id", nullable = false)
public User getProject() {
return this.project;
}
public void setProject(InitialProjectDTO project) {
this.project = project;
}
}
your Query shoud be something like this
String hql="SELECT ip from InitialProjectDTO ip JOIN ip.studentProjectDTO sp WHERE sp.projectId = :id";
Query query=session.createQuery(hql);
query.setParameter("id", id);
mail =query.list();
I am new in JPA
I created two entities Questionnaire and Patient
I want that Questionnaire will have data of Patient.
Before I created the Questionnaire with only patientId but now I want to add new structure to get all the patientData.
I added new field of patientData and added new join( I hope I did it ok ).
The problem when I call to query AllQuestionnaires I didn't get data of patientData.
Could you please advise me ?
#Entity
#NamedQueries({
#NamedQuery(name = "AllQuestionnaires", query = "select q from Questionnaire q order by q.patientId") })
public class Questionnaire implements Serializable {
private static final long serialVersionUID = 1L;
public Questionnaire() {
}
#Id
#GeneratedValue
private long id;
private long patientId;
private Timestamp created;
#OneToOne
#JoinColumn(name = "patientId" ,referencedColumnName = "id" , insertable = false, updatable = false)
private Patient patientData;
public Patient getPatient() {
return patientData;
}
public void setPatient(Patient patient) {
this.patientData = patient;
}
#OneToMany(cascade = CascadeType.ALL)
private List<QuestionnaireAnswer> answers;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getPatientId() {
return patientId;
}
public void setPatientId(long patientId) {
this.patientId = patientId;
}
public Timestamp getCreated() {
return created;
}
public void setCreated(Timestamp created) {
this.created = created;
}
public void setCreated(long created) {
this.created = new Timestamp(created);
}
public List<QuestionnaireAnswer> getAnswers() {
return answers;
}
public void setAnswers(List<QuestionnaireAnswer> answers) {
this.answers = answers;
}
}
class Patient
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Transient;
#Entity
#NamedQueries({
#NamedQuery(name = "AllPatients", query = "select p from Patient p"),
#NamedQuery(name = "PatientsByUserType", query = "select p from Patient p where p.userType = :userType"),
#NamedQuery(name = "PatientByEmail", query = "select p from Patient p where p.email = :email"),
#NamedQuery(name = "PatientById", query = "select p from Patient p where p.id = :id") })
public class Patient implements Serializable {
public enum UserType {
PATIENT,
CONTROL
}
private static final long serialVersionUID = 1L;
public Patient() {
}
#Id
#GeneratedValue
private long id;
private String firstName;
private String lastName;
private String email;
private String password;
private int gender;
private Timestamp birthday;
private Timestamp diagnoseDate;
private Timestamp created;
private UserType userType;
#Transient
private ArrayList<Task> lastSubmittedTasks;
public UserType getUserType() {
return userType;
}
public void setUserType(UserType userType) {
this.userType = userType;
}
public long getId() {
return id;
}
public void setId(long 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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public Timestamp getBirthday() {
return birthday;
}
public void setBirthday(Timestamp birthday) {
this.birthday = birthday;
}
public void setBirthday(long birthday) {
this.birthday = new Timestamp(birthday);
}
public Timestamp getDiagnoseDate() {
return diagnoseDate;
}
public void setDiagnoseDate(Timestamp diagnoseDate) {
this.diagnoseDate = diagnoseDate;
}
public void setDiagnoseDate(long diagnoseDate) {
this.diagnoseDate = new Timestamp(diagnoseDate);
}
public Timestamp getCreated() {
return created;
}
public void setCreated(Timestamp created) {
this.created = created;
}
public void setCreated(long created) {
this.created = new Timestamp(created);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public ArrayList<Task> getLastSubmittedTask() {
return lastSubmittedTasks;
}
public void setLastSubmittedTasks(ArrayList<Task> lastSubmittedTasks) {
this.lastSubmittedTasks = lastSubmittedTasks;
}
}
#RequestMapping(value = "/questionnaires", method = RequestMethod.POST)
#ResponseBody
public String createQuestionnaires(#RequestBody String body, HttpSession session) {
EntityManager em = emf.createEntityManager();
long patientId = (long) session.getAttribute("patientId");
try {
Questionnaire questionnaire = gson.fromJson(body, Questionnaire.class);
questionnaire.setPatientId(patientId);
questionnaire.setCreated(new Timestamp(System.currentTimeMillis()));
em.getTransaction().begin();
em.persist(questionnaire);
em.getTransaction().commit();
return "{\"status\": \"OK\", \"id\": " + questionnaire.getId() + "}";
} finally {
em.close();
}
}
I have set up a form that successfully insert a user product review into database. Now i'm trying to display all the reviews for the given product using c:forEach but it does not work. Basically im trying to tell the program for each selected product get productReviews but it returns blank. I have 3 classes (ProductReview, ProductHasReview, ProductHasReviewPK) that take care of holding the setter/getter methods as well as the session Beans for the entities.
Servlet
import entity.ProductHasReview;
import entity.Product;
import java.util.Collection;
import javax.ejb.EJB;
import session.ProductFacade;
#EJB
private ProductFacade productFacade;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userPath = request.getServletPath();
HttpSession session = request.getSession();
Collection<ProductHasReview> productReview = null;
// if product page is requested
} else if (userPath.equals("/viewProduct")) {
String productId = request.getQueryString();
if (productId != null) {
// get selected product
selectedProduct = productFacade.find(Integer.parseInt(productId));
// place selected product in session scope
session.setAttribute("selectedProduct", selectedProduct);
// get all reviews for selected products
productReview = selectedProduct.getProductHasReviewCollection();
// place products reviews in session scope
session.setAttribute("productReview", productReview);
}
userPath = "/product";
Product.jsp
<c:forEach var="product" items="${productReview}" varStatus="iter">
<div class="content ProdReviewRow">
<h3>${productReview.name}, ${productReview.age}, ${productReview.gender} </h3>
<h6>${productReview.dateCreated}<h6>
${productReview.review}
</div>
</c:forEach>
Product.java
package entity;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#Entity
#Table(name = "product")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p"),
#NamedQuery(name = "Product.findById", query = "SELECT p FROM Product p WHERE p.id = :id"),
#NamedQuery(name = "Product.findByPrice", query = "SELECT p FROM Product p WHERE p.price = :price"),
#NamedQuery(name = "Product.findByLastUpdate", query = "SELECT p FROM Product p WHERE p.lastUpdate = :lastUpdate")})
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Lob
#Size(min = 1, max = 16777215)
#Column(name = "name")
private String name;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Basic(optional = false)
#NotNull
#Column(name = "price")
private BigDecimal price;
#Basic(optional = false)
#NotNull
#Lob
#Size(min = 1, max = 2147483647)
#Column(name = "description")
private String description;
#Basic(optional = false)
#NotNull
#Column(name = "last_update")
#Temporal(TemporalType.TIMESTAMP)
private Date lastUpdate;
#Basic(optional = false)
#NotNull
#Lob
#Size(min = 1, max = 2147483647)
#Column(name = "faq")
private String faq;
#ManyToMany(mappedBy = "productCollection")
private Collection<Category> categoryCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
private Collection<ProductHasBadRating> productHasBadRatingCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
private Collection<OrderedProduct> orderedProductCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
private Collection<ProductHasGoodRating> productHasGoodRatingCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
private Collection<ProductHasReview> productHasReviewCollection;
public Product() {
}
public Product(Integer id) {
this.id = id;
}
public Product(Integer id, String name, BigDecimal price, String description, Date lastUpdate, String faq) {
this.id = id;
this.name = name;
this.price = price;
this.description = description;
this.lastUpdate = lastUpdate;
this.faq = faq;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
public String getFaq() {
return faq;
}
public void setFaq(String faq) {
this.faq = faq;
}
#XmlTransient
public Collection<Category> getCategoryCollection() {
return categoryCollection;
}
public void setCategoryCollection(Collection<Category> categoryCollection) {
this.categoryCollection = categoryCollection;
}
#XmlTransient
public Collection<ProductHasBadRating> getProductHasBadRatingCollection() {
return productHasBadRatingCollection;
}
public void setProductHasBadRatingCollection(Collection<ProductHasBadRating> productHasBadRatingCollection) {
this.productHasBadRatingCollection = productHasBadRatingCollection;
}
#XmlTransient
public Collection<OrderedProduct> getOrderedProductCollection() {
return orderedProductCollection;
}
public void setOrderedProductCollection(Collection<OrderedProduct> orderedProductCollection) {
this.orderedProductCollection = orderedProductCollection;
}
#XmlTransient
public Collection<ProductHasGoodRating> getProductHasGoodRatingCollection() {
return productHasGoodRatingCollection;
}
public void setProductHasGoodRatingCollection(Collection<ProductHasGoodRating> productHasGoodRatingCollection) {
this.productHasGoodRatingCollection = productHasGoodRatingCollection;
}
#XmlTransient
public Collection<ProductHasReview> getProductHasReviewCollection() {
return productHasReviewCollection;
}
public void setProductHasReviewCollection(Collection<ProductHasReview> productHasReviewCollection) {
this.productHasReviewCollection = productHasReviewCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Product)) {
return false;
}
Product other = (Product) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entity.Product[ id=" + id + " ]";
}
}
ProductReview.java
#Entity
#Table(name = "product_review")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "ProductReview.findAll", query = "SELECT p FROM ProductReview p"),
#NamedQuery(name = "ProductReview.findById", query = "SELECT p FROM ProductReview p WHERE p.id = :id"),
#NamedQuery(name = "ProductReview.findByName", query = "SELECT p FROM ProductReview p WHERE p.name = :name"),
#NamedQuery(name = "ProductReview.findByDateCreated", query = "SELECT p FROM ProductReview p WHERE p.dateCreated = :dateCreated"),
#NamedQuery(name = "ProductReview.findByCountry", query = "SELECT p FROM ProductReview p WHERE p.country = :country"),
#NamedQuery(name = "ProductReview.findByAge", query = "SELECT p FROM ProductReview p WHERE p.age = :age"),
#NamedQuery(name = "ProductReview.findByGender", query = "SELECT p FROM ProductReview p WHERE p.gender = :gender"),
#NamedQuery(name = "ProductReview.findByEmail", query = "SELECT p FROM ProductReview p WHERE p.email = :email")})
public class ProductReview implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Lob
#Size(max = 2147483647)
#Column(name = "review")
private String review;
#Size(max = 45)
#Column(name = "name")
private String name;
#Column(name = "date_created")
#Temporal(TemporalType.TIMESTAMP)
private Date dateCreated;
#Size(max = 45)
#Column(name = "country")
private String country;
#Size(max = 45)
#Column(name = "age")
private String age;
#Size(max = 45)
#Column(name = "gender")
private String gender;
// #Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
#Size(max = 45)
#Column(name = "email")
private String email;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "productReview")
private Collection<ProductHasReview> productHasReviewCollection;
public ProductReview() {
}
public ProductReview(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#XmlTransient
public Collection<ProductHasReview> getProductHasReviewCollection() {
return productHasReviewCollection;
}
public void setProductHasReviewCollection(Collection<ProductHasReview> productHasReviewCollection) {
this.productHasReviewCollection = productHasReviewCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof ProductReview)) {
return false;
}
ProductReview other = (ProductReview) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entity.ProductReview[ id=" + id + " ]";
}
}
ProductHasReview.java
package entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author PC
*/
#Entity
#Table(name = "product_has_review")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "ProductHasReview.findAll", query = "SELECT p FROM ProductHasReview p"),
#NamedQuery(name = "ProductHasReview.findByProductId", query = "SELECT p FROM ProductHasReview p WHERE p.productHasReviewPK.productId = :productId"),
#NamedQuery(name = "ProductHasReview.findByProductReviewId", query = "SELECT p FROM ProductHasReview p WHERE p.productHasReviewPK.productReviewId = :productReviewId"),
#NamedQuery(name = "ProductHasReview.findByQuantity", query = "SELECT p FROM ProductHasReview p WHERE p.quantity = :quantity")})
public class ProductHasReview implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected ProductHasReviewPK productHasReviewPK;
#Column(name = "quantity")
private Short quantity;
#JoinColumn(name = "product_id", referencedColumnName = "id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Product product;
#JoinColumn(name = "product_review_id", referencedColumnName = "id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private ProductReview productReview;
public ProductHasReview() {
}
public ProductHasReview(ProductHasReviewPK productHasReviewPK) {
this.productHasReviewPK = productHasReviewPK;
}
public ProductHasReview(int productId, int productReviewId) {
this.productHasReviewPK = new ProductHasReviewPK(productId, productReviewId);
}
public ProductHasReviewPK getProductHasReviewPK() {
return productHasReviewPK;
}
public void setProductHasReviewPK(ProductHasReviewPK productHasReviewPK) {
this.productHasReviewPK = productHasReviewPK;
}
public Short getQuantity() {
return quantity;
}
public void setQuantity(Short quantity) {
this.quantity = quantity;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public ProductReview getProductReview() {
return productReview;
}
public void setProductReview(ProductReview productReview) {
this.productReview = productReview;
}
#Override
public int hashCode() {
int hash = 0;
hash += (productHasReviewPK != null ? productHasReviewPK.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof ProductHasReview)) {
return false;
}
ProductHasReview other = (ProductHasReview) object;
if ((this.productHasReviewPK == null && other.productHasReviewPK != null) || (this.productHasReviewPK != null && !this.productHasReviewPK.equals(other.productHasReviewPK))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entity.ProductHasReview[ productHasReviewPK=" + productHasReviewPK + " ]";
}
}
I have created Three classes- User, UserSubscription and Subscription. I want that users in the UserSubscription table should be referenced by the users existing in the User table. So, how to use mappedBy?
The classes are as follows:
User:
package com.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
#Entity
public class User {
private int userId;
private String password;
private String contact;
private String firstName;
private String lastName;
private String gender;
private String address;
private int age;
private String email;
private String countBooks;
private Set<Language> languages = new HashSet<Language>(0);
private Set<Book> favorites = new HashSet<Book>(0);
#Id
#GeneratedValue
#Column(name="User_Id")
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
#Column(name="Password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name="Contact")
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
#Column(name="First_Name")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name="Last_Name")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name="Gender")
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
#Column(name="Address")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
#Column(name="Age")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Column(name="Email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name="Count_Books")
public String getCountBooks() {
return countBooks;
}
public void setCountBooks(String countBooks) {
this.countBooks = countBooks;
}
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="User_Language", joinColumns = {
#JoinColumn(name = "User_Id", nullable = false, updatable = false) },
inverseJoinColumns = { #JoinColumn(name = "Language_Id",
nullable = false, updatable = false) })
public Set<Language> getLanguages() {
return languages;
}
public void setLanguages(Set<Language> languages) {
this.languages = languages;
}
#ManyToMany
#JoinTable(name="User_Favorite", joinColumns = {
#JoinColumn(name = "User_Id", nullable = false, updatable = false) },
inverseJoinColumns = { #JoinColumn(name = "Book_Id",
nullable = false, updatable = false) })
public Set<Book> getFavorites() {
return favorites;
}
public void setFavorites(Set<Book> favorites) {
this.favorites = favorites;
}
}
UserSubscription:
package com.model;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
#Entity
public class UserSubscription {
private int userSubscriptionId;
private Subscription subscription;
private User user;
private Date subscriptionStartDate;
private Date subscriptionEndDate;
private int status;
#Id
#GeneratedValue
#Column(name="User_Subscription_Id")
public int getUserSubscriptionId() {
return userSubscriptionId;
}
public void setUserSubscriptionId(int userSubscriptionId) {
this.userSubscriptionId = userSubscriptionId;
}
#Column(name="Subscription_Id")
public Subscription getSubscription() {
return subscription;
}
public void setSubscription(Subscription subscription) {
this.subscription = subscription;
}
#OneToOne(mappedBy="userId")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name="Subscription_Start_Date")
public Date getSubscriptionStartDate() {
return subscriptionStartDate;
}
public void setSubscriptionStartDate(Date subscriptionStartDate) {
this.subscriptionStartDate = subscriptionStartDate;
}
#Column(name="Subscription_End_Date")
public Date getSubscriptionEndDate() {
return subscriptionEndDate;
}
public void setSubscriptionEndDate(Date subscriptionEndDate) {
this.subscriptionEndDate = subscriptionEndDate;
}
#Column(name="Status")
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
Subscription:
package com.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Subscription {
private int subscriptionId;
private String name;
private int period;
private float fees;
private int noOfBooks;
private int Status;
#Id
#GeneratedValue
public int getSubscriptionId() {
return subscriptionId;
}
public void setSubscriptionId(int subscriptionId) {
this.subscriptionId = subscriptionId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPeriod() {
return period;
}
public void setPeriod(int period) {
this.period = period;
}
public float getFees() {
return fees;
}
public void setFees(float fees) {
this.fees = fees;
}
public int getNoOfBooks() {
return noOfBooks;
}
public void setNoOfBooks(int noOfBooks) {
this.noOfBooks = noOfBooks;
}
public int getStatus() {
return Status;
}
public void setStatus(int status) {
Status = status;
}
}
Exception while executing:
Exception in thread "main" org.hibernate.AnnotationException: Referenced property not a (One|Many)ToOne: com.model.User.userId in mappedBy of com.model.UserSubscription.user
at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:248)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1695)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)
at com.impetus.model.Check.main(Check.java:92)
In your code, user-user_subscription looks uni-directional. 'mappedby' should be used in bi-directional relationship.
You can use following code in user entity to make it bi-directional with user_subscription.
private UserSubscription userSubscription;
#OneToOne
public User getUserSubscription() {
return userSubscription;
}
Or remove mappedby from user_subscription and make it unidirectional.
Seems you are unsure of what mappedBy is used for or means. Database relationships are one sided; one table will have a foreign key reference to the target table. In JPA, you might map this relationship as a OneToOne and specify the foreign key to use with the #JoinColumn annotation:
#OneToOne(mappedBy="userId")
#JoinColumn(name = "USER_ID")
public User getUser() {
return user;
}
The Join column definition is optional, and if not used JPA will default to using the attribute name with "_" and the target entity's ID name prepended, so "USER_ID" in this case anyway.
Back to the database, because target table is referenced by the source table, this forms another implicit relationship back (the target table's ID can be used to look up the other table's foreign key). In JPA, this can be mapped again as a OneToOne or a OneToMany depending on the cardinality. If it is a OneToOne, you specify that this relationship does not define the foreign key by marking it as mappedBy the other relationship:
#OneToOne(mappedBy="user")
public UserSubscription getUserSubscription() {
return userSubscription;
}
But it is more likely a User will have multiple userSubscriptions:
#OneToMany(mappedBy="user")
public Collection<UserSubscription> getUserSubscriptions () {
return userSubscription ;
}
In both cases, you use the mappedBy to signal that there is a 'user' attribute in the target entity that defines a relationship to this entity and controls the foreign key setting in the database.
You also need to change how your define the UserSubscription->Subscription relationship, as you have defined an #Column on what appears to be a relationship. It should probably be
#OneToOne
#JoinColumn(name="Subscription_Id")
public Subscription getSubscription() {
return subscription;
}
you should have UserSubscription memeber and corrosponding gettes and setters in your User class like below:
private Set<Company> userSubscriptions = new HashSet<Company>(0);
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
public Set<UserSubscription> getUserSubscriptions() {
return this.userSubscriptions ;
}
public void setUserSubscriptions(Set<UserSubscription> userSubscriptions ) {
this.userSubscriptions = userSubscriptions ;
}
and same way you should have user object as memeber in UserSubscription Entity class.
private User user;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "USER_ID", nullable = false)
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
You are doing it wrong
class User {
UserSubscription userSubscription ;
#OneToOne
public UserSubscription getUserSubscription(){
return userSubscription ;
}
public void setUserSubscription(UserSubscription userSubscription ){
this.userSubscription = userSubscription ;
}
}
class UserSubscription {
#OneToOne(mappedBy="userSubscription")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
I get following exception when I try to display data from EmergencyContact. SurveyData and EmergencyData are related by OneToMany. I'm able to persist the data but not able to retrieve it back.
I want to give a SurveyID as input and get back emergency contacts of that survey. I verified all my setter and getter methods and they look okay. I'm unable to trace where I made mistake. Any help is appreciated.
16:53:42,029 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) Caused by: org.hibernate.QueryException: could not resolve property: survey_id of: masonsurveyejb.businesslogic.EmergencyContact [SELECT emc FROM masonsurveyejb.businesslogic.EmergencyContact emc WHERE emc.survey_id = 11]
My query string looks like below. I receive survey_id variable value as an argument in this method.
"SELECT emc FROM EmergencyContact emc WHERE emc.survey_id = " + survey_id
Following are my EmergencyContact and SurveyData classes
package masonsurveyejb.businesslogic;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name = "EmergencyData")
public class EmergencyContact implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "EMERGENCY_SEQUENCE", sequenceName = "Survey_Seq", initialValue = 100, allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EMERGENCY_SEQUENCE")
private Integer contactId;
#Column(name = "Name")
private String emName;
#Column(name = "Phone")
private String emPhone;
#Column(name = "Email")
private String emEmail;
#ManyToOne
#JoinColumn(name = "SurveyID")
private SurveyData surveyData;
public Integer getContactId() {
return contactId;
}
public void setContactId(Integer contactId) {
this.contactId = contactId;
}
public SurveyData getSurveyData() {
return surveyData;
}
public void setSurveyData(SurveyData surveyData) {
this.surveyData = surveyData;
}
public String getEmName() {
return emName;
}
public void setEmName(String emName) {
this.emName = emName;
}
public String getEmPhone() {
return emPhone;
}
public void setEmPhone(String emPhone) {
this.emPhone = emPhone;
}
public String getEmEmail() {
return emEmail;
}
public void setEmEmail(String emEmail) {
this.emEmail = emEmail;
}
}
///////////////////////////////////////////////////////////////////////////////
// #filename: Student.java
// #description: This file is the a simple class which is used as a model
// object for Student.
//
// Modification History
// Date Author Change Reason
// ==== ====== =============
// 2014-02-20 Santosh K Tadikonda Initial Creation
//
///////////////////////////////////////////////////////////////////////////////
package masonsurveyejb.businesslogic;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
#Entity
public class SurveyData {
#Id
#SequenceGenerator(name = "SURVEY_SEQUENCE", sequenceName = "Survey_Seq", initialValue = 100, allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SURVEY_SEQUENCE")
#Column(name = "SurveyID")
private Integer survey_id;
private String firstname;
private String lastname;
private String address;
private String city;
private String state;
private String zipcode;
private String telephone;
private String email;
private String surveydate;
#Column(name = "Likes")
private String chklike;
#Column(name = "Know")
private String radioknow;
private String recommend;
private String raffle;
private String comments;
#OneToMany(mappedBy = "surveyData", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<EmergencyContact> emContacts;
public List<EmergencyContact> getEmContacts() {
return emContacts;
}
public void setEmContacts(List<EmergencyContact> emContacts) {
this.emContacts = emContacts;
}
public Integer getSurvey_id() {
return survey_id;
}
public void setSurvey_id(Integer survey_id) {
this.survey_id = survey_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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSurveydate() {
return surveydate;
}
public void setSurveydate(String surveydate) {
this.surveydate = surveydate;
}
public String getChklike() {
return chklike;
}
public void setChklike(String chklike) {
this.chklike = chklike;
}
public String getRadioknow() {
return radioknow;
}
public void setRadioknow(String radioknow) {
this.radioknow = radioknow;
}
public String getRecommend() {
return recommend;
}
public void setRecommend(String recommend) {
this.recommend = recommend;
}
public String getRaffle() {
return raffle;
}
public void setRaffle(String raffle) {
this.raffle = raffle;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String toString() {
String studentString;
studentString = getSurvey_id() + ";" +getFirstname() + ";" + getLastname() + ";"
+ getAddress() + ";" + getCity() + ";" + getState() + ";"
+ getZipcode() + ";" + getTelephone() + ";" + getEmail() + ";"
+ getSurveydate() + ";" + getChklike() + ";" + getRadioknow()
+ ";" + getRecommend() + ";" + getRaffle() + ";"
+ getComments();
return studentString;
}
}
Following is the method from which I make query
#Override
public ArrayList<EmergencyContact> GetEmergencyContacts(String survey_id) {
try {
if (survey_id == null || survey_id.length() == 0) {
System.out.println("Received a null or empty survey ID.");
return null;
}
System.out.println("Getting emergency contacts for " + survey_id);
String queryStr = "SELECT emc FROM EmergencyContact emc WHERE emc.survey_id = "
+ survey_id;
Query query = entityManager.createQuery(queryStr);
List resultList = query.getResultList();
if (resultList != null && resultList.size() > 0) {
ArrayList<EmergencyContact> emList = new ArrayList<EmergencyContact>();
for (Object result : resultList) {
EmergencyContact emc = new EmergencyContact();
emc = (EmergencyContact) result;
emList.add(emc);
}
return emList;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
You receiving the exception because entity 'EmergencyContact' has no property named 'survey_id'.
Your query should be:
String queryStr = "SELECT emc FROM EmergencyContact emc WHERE emc.surveyData.survey_id = :id";
Query query = entityManager.createQuery(queryStr).setParameter("id", survey_id);
List resultList = query.getResultList();
Please consider 2 things:
Use property names in JPQL query (surveyData.survey_id)
It's better to set query parameters with special method, "setParameter"