Hibernate, display join left results in Spring - java

I'm learning Spring and Hibernate and i have small but quite important problem.
I want to get data from database:
Query query = session.createSQLQuery("SELECT * FROM pool a LEFT JOIN pool_question b on a.id = b.poolid");
and then sent results as list to jsp file from my controller
model.addAttribute("pools", pool);
My database is quite simple:
pool is:
id name slug date_create deactivation_date creator_id active
and poolquestion is
id poolid answer order question
The problem is, that when i'm trying to make a loop in jsp:
<c:forEach items="${pools}" var="pool">
<td><c:out value="${pool.name}" /></td>
</c:forEach>
tomcat displays me error.
When i check my query in phpmyadmin the result is ok.
The trick is, that when i do query like this:
Query query = session.createQuery("FROM Pool");
The results in jsp are displayed properly.
Could enyone help me how to display result of this query in jsp?
My Pool.java is:
package com.pool.app.domain;
// Generated 2011-12-20 12:45:22 by Hibernate Tools 3.4.0.CR1
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* Pool generated by hbm2java
*/
#Entity
#Table(name = "pool", catalog = "pool")
public class Pool implements java.io.Serializable {
private Integer id;
private String name;
private String slug;
private Date dateCreate;
private Date deactivationDate;
private int creatorId;
private int active;
private Set<PoolQuestion> poolQuestions = new HashSet<PoolQuestion>(0);
public Pool() {
}
public Pool(String name, String slug, Date dateCreate,
Date deactivationDate, int creatorId, int active) {
this.name = name;
this.slug = slug;
this.dateCreate = dateCreate;
this.deactivationDate = deactivationDate;
this.creatorId = creatorId;
this.active = active;
}
public Pool(String name, String slug, Date dateCreate,
Date deactivationDate, int creatorId, int active,
Set<PoolQuestion> poolQuestions) {
this.name = name;
this.slug = slug;
this.dateCreate = dateCreate;
this.deactivationDate = deactivationDate;
this.creatorId = creatorId;
this.active = active;
this.poolQuestions = poolQuestions;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name", nullable = false, length = 200)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "slug", nullable = false, length = 200)
public String getSlug() {
return this.slug;
}
public void setSlug(String slug) {
this.slug = slug;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "date_create", nullable = false, length = 19)
public Date getDateCreate() {
return this.dateCreate;
}
public void setDateCreate(Date dateCreate) {
this.dateCreate = dateCreate;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "deactivation_date", nullable = false, length = 19)
public Date getDeactivationDate() {
return this.deactivationDate;
}
public void setDeactivationDate(Date deactivationDate) {
this.deactivationDate = deactivationDate;
}
#Column(name = "creator_id", nullable = false)
public int getCreatorId() {
return this.creatorId;
}
public void setCreatorId(int creatorId) {
this.creatorId = creatorId;
}
#Column(name = "active", nullable = false)
public int getActive() {
return this.active;
}
public void setActive(int active) {
this.active = active;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pool")
public Set<PoolQuestion> getPoolQuestions() {
return this.poolQuestions;
}
public void setPoolQuestions(Set<PoolQuestion> poolQuestions) {
this.poolQuestions = poolQuestions;
}
}
and PoolQuestion.java is:
package com.pool.app.domain;
// Generated 2011-12-20 12:45:22 by Hibernate Tools 3.4.0.CR1
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* PoolQuestion generated by hbm2java
*/
#Entity
#Table(name = "pool_question", catalog = "pool")
public class PoolQuestion implements java.io.Serializable {
private Integer id;
private Pool pool;
private String answer;
private int order;
private String question;
public PoolQuestion() {
}
public PoolQuestion(Pool pool, String answer, int order) {
this.pool = pool;
this.answer = answer;
this.order = order;
}
public PoolQuestion(Pool pool, String answer, int order, String question) {
this.pool = pool;
this.answer = answer;
this.order = order;
this.question = question;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "poolid", nullable = false)
public Pool getPool() {
return this.pool;
}
public void setPool(Pool pool) {
this.pool = pool;
}
#Column(name = "answer", nullable = false, length = 500)
public String getAnswer() {
return this.answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
#Column(name = "order", nullable = false)
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
#Column(name = "question", length = 500)
public String getQuestion() {
return this.question;
}
public void setQuestion(String question) {
this.question = question;
}
}
And the main question - how the HQL query should looks, becouse query like this:
Query query = session.createQuery("From Pool as p left join fetch p.id as s");
doesn't works for me.

Without the exception it's hard to know exactly what's going wrong. However, have a read of:
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querysql.html
I think you're problem is that you're using createSQLQuery instead of createQuery. Ie you're using standard SQL instead of HQL. To get you started, try changing your query to:
SELECT a.* FROM pool a LEFT JOIN ...
and make a call to .addEntity(Pool.class), ie session.createSQLQuery("<use above SQL>").addEntity(Pool.class);
Good luck.

Query query = session.createQuery("from Pool");
Is an HQL query, it will give you a list of Objects (Pool), so there is no problem to use :
<c:forEach items="${pools}" var="pool">
<td><c:out value="${pool.name}" /></td>
</c:forEach>
when you use an SQL query, it's different, you will not get a list of objects (you have to add some code and transformations to get a list of pools).
Here an example :
#SuppressWarnings({ "unchecked", "rawtypes" })
public List<Pool> findPools()
{
final String query = "select a.id as idAlias, a.name as nameAlias from pool a ....";
List<Pool> list = (List<Pool>) getHibernateTemplate().execute(new HibernateCallback()
{
public Object doInHibernate(Session session) throws HibernateException
{
SQLQuery sqlQuery = session.createSQLQuery(query);
return prepareQueryFind(sqlQuery).list();
}
});
return list;
}
Here i suppose you have a constructor like :
public Pool(Integer id, String name);
/** Getters and Setters **/
if you are using Hibernate version >= 3.2
#SuppressWarnings("deprecation")
private Query prepareQueryFind(SQLQuery query)
{
return query
.addScalar("idAlias", Hibernate.INTEGER)
.addScalar("nameAlias", Hibernate.STRING)
.setResultTransformer(Transformers.aliasToBean(Pool.class));
}
Now you can call fidpools like this :
List<Pool> poolList = poolDao.findPools();

When using Hibernate You don't usually want to use native SQL but rather HQL.
If you are using native query createSQLQuery then you have to specify explicitly How should be values mapped to your POJO or specify scalars - see hibernate documentation.
And why are you using this query in the first place? Can't you obtain the poolquestion values from some association mapping of Pool class? That's the whole point of Hibernate.
Let me be more clear.
First forget the join in query. You don't need it. You want POJO instances no some crazy result set of outer join.
Query all Pool data as you did Query query = session.createQuery("FROM Pool");
Get list containing Pool instances representing your data List<Pool> pools = (List<Pool>) query.list();
Now you have it. All associated data are obtained by Hibernate lazily when you ask for them - pool.getPoolQuestions();

You can try this:
Query hqlQuery = session.createQuery("from Pool as P left join P.poolQuestion");
You can look for more here.
Some advice:
If you are using Hibernate and Spring, why you don't use getHibernateTemplate() to get your data from tables? In this case you can use:
List<Pool> result = (List<Pool>) getHibernateTemplate().find("from Pool");
and all you data will be in this result.
For more details you can follow this example.
Please check if I'm right, because I haven't tested/simulated it.

Related

How to recover a product entity with this query below?

I'm waiting for a product type entity object with the quantity and total cahmps containing the values ​​of SUM (lc.quantity) as quantite, SUM (lc.montant) as total, but I get an object of type java.lang.object
This is my query
#NamedQuery(name = "Produit.findAllBuyPorductGroupByProduct",
query = "SELECT p, SUM(lc.quantite) quantite, SUM(lc.montant) total
FROM LigneCommande lc JOIN lc.produit p
GROUP BY p")
This is my product entity
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.instantech.stogeg.data.base.entity;
import java.io.Serializable;
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.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author instantech
*/
#Entity
#Table(name = "produit")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Produit.findAll", query = "SELECT p FROM Produit p")
, #NamedQuery(name = "Produit.findById", query = "SELECT p FROM Produit p WHERE p.id = :id")
, #NamedQuery(name = "Produit.findByReference", query = "SELECT p FROM Produit p WHERE p.reference = :reference")
, #NamedQuery(name = "Produit.findByDesignation", query = "SELECT p FROM Produit p WHERE p.designation = :designation")
, #NamedQuery(name = "Produit.findByStock", query = "SELECT p FROM Produit p WHERE p.stock = :stock")
, #NamedQuery(name = "Produit.findAllBuyPorductGroupByProduct", query = "SELECT p, SUM(lc.quantite) quantite, SUM(lc.montant) total FROM LigneCommande lc JOIN lc.produit p GROUP BY p")
, #NamedQuery(name = "Produit.findBy_", query = "SELECT p FROM Produit p WHERE CAST(p.id as CHAR) LIKE :numeroProduit OR CAST(p.pu as CHAR) LIKE :pu OR CAST(p.stock as CHAR) LIKE :stock OR p.reference LIKE :reference OR p.designation LIKE :designation ORDER BY p.designation")
, #NamedQuery(name = "Produit.findByPu", query = "SELECT p FROM Produit p WHERE p.pu = :pu")
, #NamedQuery(name = "Produit.findByDate", query = "SELECT p FROM Produit p WHERE p.date = :date")
, #NamedQuery(name = "Produit.findByHeure", query = "SELECT p FROM Produit p WHERE p.heure = :heure")})
public class Produit 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)
#Column(name = "reference")
private String reference;
#Basic(optional = false)
#Column(name = "designation")
private String designation;
#Basic(optional = false)
#Column(name = "stock")
private int stock;
#Basic(optional = false)
#Column(name = "pu")
private float pu;
#Basic(optional = false)
#Column(name = "date")
#Temporal(TemporalType.DATE)
private Date date;
#Basic(optional = false)
#Column(name = "heure")
#Temporal(TemporalType.TIME)
private Date heure;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "produit")
private Collection<LigneCommande> ligneCommandeCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "produit")
private Collection<HistoryStock> historyStockCollection;
#Transient
private int quantite;
#Transient
private double total;
public Produit() {
}
public Produit(Integer id) {
this.id = id;
}
public Produit(Integer id, String reference, String designation, int stock, float pu, Date date, Date heure) {
this.id = id;
this.reference = reference;
this.designation = designation;
this.stock = stock;
this.pu = pu;
this.date = date;
this.heure = heure;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getReference() {
return reference;
}
public void setReference(String reference) {
this.reference = reference;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
public float getPu() {
return pu;
}
public void setPu(float pu) {
this.pu = pu;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Date getHeure() {
return heure;
}
public void setHeure(Date heure) {
this.heure = heure;
}
#XmlTransient
public Collection<LigneCommande> getLigneCommandeCollection() {
return ligneCommandeCollection;
}
public void setLigneCommandeCollection(Collection<LigneCommande> ligneCommandeCollection) {
this.ligneCommandeCollection = ligneCommandeCollection;
}
#XmlTransient
public Collection<HistoryStock> getHistoryStockCollection() {
return historyStockCollection;
}
public void setHistoryStockCollection(Collection<HistoryStock> historyStockCollection) {
this.historyStockCollection = historyStockCollection;
}
#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 Produit)) {
return false;
}
Produit other = (Produit) object;
return !((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id)));
}
#Override
public String toString() {
return this.getDesignation() + " ( "+this.getStock()+ " ) ";
}
public Object[] getProduit(){
return new Object [] {
this.getId(), this.getReference(), this.getDesignation(), this.getStock(), this.getPu()
};
}
public int updateStock(int quantite) throws Exception{
if(quantite > this.getStock())
throw new Exception("Le stock du produit est inférieur à la quantité commandé");
else
return (this.getStock() - quantite);
}
public int adQuantity(int quantite) throws Exception{
if(quantite > 0){
return (this.getStock() + quantite);
}else{
throw new Exception("Le stock du produit est ne peut pas être null ou négatif");
}
}
public int getQuantite() {
return quantite;
}
public void setQuantite(int quantite) {
this.quantite = quantite;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
}
This is my line command entity
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.instantech.stogeg.data.base.entity;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Basic;
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.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author instantech
*/
#Entity
#Table(name = "ligne_commande")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "LigneCommande.findAll", query = "SELECT l FROM LigneCommande l")
, #NamedQuery(name = "LigneCommande.findById", query = "SELECT l FROM LigneCommande l WHERE l.id = :id")
, #NamedQuery(name = "LigneCommande.findByQuantite", query = "SELECT l FROM LigneCommande l WHERE l.quantite = :quantite")
, #NamedQuery(name = "LigneCommande.findByMontant", query = "SELECT l FROM LigneCommande l WHERE l.montant = :montant")})
public class LigneCommande implements Serializable {
#Basic(optional = false)
#Column(name = "date")
#Temporal(TemporalType.DATE)
private Date date;
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#Column(name = "quantite")
private int quantite;
#Basic(optional = false)
#Column(name = "montant")
private double montant;
#ManyToMany(mappedBy = "ligneCommandeCollection")
private Collection<Commande> commandeCollection;
#JoinColumn(name = "produit", referencedColumnName = "id")
#ManyToOne(optional = false)
private Produit produit;
public LigneCommande() {
}
public LigneCommande(Integer id) {
this.id = id;
}
public LigneCommande(Integer id, int quantite, double montant, Date date) {
this.id = id;
this.quantite = quantite;
this.montant = montant;
this.date = date;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getQuantite() {
return quantite;
}
public void setQuantite(int quantite) {
this.quantite = quantite;
}
public double getMontant() {
return montant;
}
public void setMontant(double montant) {
this.montant = montant;
}
#XmlTransient
public Collection<Commande> getCommandeCollection() {
return commandeCollection;
}
public void setCommandeCollection(Collection<Commande> commandeCollection) {
this.commandeCollection = commandeCollection;
}
public Produit getProduit() {
return produit;
}
public void setProduit(Produit produit) {
this.produit = produit;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
if (!(object instanceof LigneCommande)) {
return false;
}
LigneCommande other = (LigneCommande) object;
return !((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id)));
}
#Override
public String toString() {
return "com.instantech.entity.LigneCommande[ id=" + id + " ]";
}
public void addQuantite(int quantite){
this.quantite += quantite;
}
public double getTotal() {
return this.getQuantite() * this.getProduit().getPu();
}
public Object[] getLigneCommande(){
return new Object[] {
this.getProduit().getReference(),
this.getProduit().getDesignation(),
this.getQuantite(),
String.format("%, .0f",this.getProduit().getPu()),
String.format("%, .0f",this.getTotal())
};
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
The function that retrieves the result of my query
/**
* Return list of product that grouped by product
*
* #return
*/
public List<Produit> findProductGroupBy() {
TypedQuery<Produit> query = this.getEntitymanager().createNamedQuery("Produit.findAllBuyPorductGroupByProduct", Produit.class);
return query.getResultList();
}
Test of my query
public class test {
private static ProduitManager pm;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
pm = new ProduitManager();
pm.findProductGroupBy().forEach((p)->{
System.out.println(p);
});
pm.close();
}
}
This is the result after execution
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.instantech.stogeg.data.base.entity.Produit
at java.util.Vector.forEach(Vector.java:1275)
at test.main(test.java:22)
NB: In my product table in the database, the quantity and total field that are in my product entity are not there.
1) Create some sort of a TO:
public class ResultDTO{
private Product product;
private Integer quantity;
private Double total;
public ResultDTO(Product product, Integer quantity, Double total){
// set fields
}
2) Alter the query to use that class:
#NamedQuery(name = "Produit.findAllBuyPorductGroupByProduct",
query = "SELECT new com.mypackage.ResultDTO(
p as product, SUM(lc.quantite) as quantity, SUM(lc.montant) as total)
FROM LigneCommande lc JOIN lc.produit p
GROUP BY p")
3) Change generic type to ResultDTO:
public List<ResultDTO> findProductGroupBy() {
TypedQuery<ResultDTO> query = this.getEntitymanager().createNamedQuery(
"Produit.findAllBuyPorductGroupByProduct", ResultDTO.class);
return query.getResultList();
}
What you are looking for is called projections. How to use them is very thoroughly explained over here. They work better than custom objects (via new keyword) because they support native queries and are generally easier to understand.
Step 1: Declare a simple bean data transfer object (dto)
#Data
#NoArgsConstructor
#AllArgsConstructor
public class ProductSummaryDto {
private Product product;
private Integer quantity;
private Double total;
}
Step 2: Create custom spring data query in your repository
#Query("SELECT p product, SUM(lc.quantite) quantity, SUM(lc.montant) total FROM LigneCommande lc JOIN lc.produit p GROUP BY p")
List<ProductSummaryDto> getProductSummaries();

Join in hibernate with annotaion

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();

Jersey JAX-RS auto-generated webservices and MSSQL Identity fields

I can't get working the Jersey RESTful webservices, autogenerated with Netbeans.
When POSTing the JSON like this,
{"name":"Some New Site"}
the POST query returns me this,
Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot insert
explicit value for identity column in table 'site' when IDENTITY_INSERT is set to OFF.
Error Code: 544
Call: INSERT INTO site (id, name) VALUES (?, ?)
bind => [2 parameters bound]
Unlike MySQL, MSSQL doesn't generate new autoincremented ID when the NULL value is passed in INSERT query; it needs the ID field not to mentioned at all to generate value for it.
(IDENTITY_INSERT will not make ID to be generated either)
How do I teach my Jersey services to omit the id field in INSERT query?
edit: here's the POJO, it was generated automatically for me by Netbeans with it's "Restful Web Services From Database" wizard. (I am trying to be as little original as possible)
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package ru.fedd.entities;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author fkravchenko
*/
#Entity
#Table(name = "site")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Site.findAll", query = "SELECT s FROM Site s"),
#NamedQuery(name = "Site.findById", query = "SELECT s FROM Site s WHERE s.id = :id"),
#NamedQuery(name = "Site.findByName", query = "SELECT s FROM Site s WHERE s.name = :name")})
public class Site implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "id")
private Long id;
#Basic(optional = false)
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "siteId")
private Collection<Document> documentCollection;
public Site() {
}
public Site(Long id) {
this.id = id;
}
public Site(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlTransient
public Collection<Document> getDocumentCollection() {
return documentCollection;
}
public void setDocumentCollection(Collection<Document> documentCollection) {
this.documentCollection = documentCollection;
}
#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 Site)) {
return false;
}
Site other = (Site) 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 "ru.fedd.entities.Site[ id=" + id + " ]";
}
}
Can you share your POJO class here?
You probably have to annotate your id of the POJO class with #GeneratedValue to notify it is auto generated. Then JPA will take care of the insertion.

JPA/Hibernate persist does not appear to work

I'm using JPA (Hibernate implementation) to save objects to the database. Selecting works fine, but for some reason, saving doesn't work. I don't get any errors, but the database doesn't get changed either. This goes for both new entities and existing ones.
EPayment pay = new EPayment();
pay.setAmount(payment.getAmount());
...
pay.setUserByToUserId(receiver);
CompayDAO.get().save(pay);
CompayDAO.save()
public void save(Object ent) {
System.out.println("Persisting: " + ent + " using " + this);
this.em.persist(ent);
}
Console output:
Opening DOA nl.compay.entities.CompayDAO#b124fa
Persisting: nl.compay.entities.EUser#1e2fe5d using nl.compay.entities.CompayDAO#b124fa
Persisting: nl.compay.entities.EUser#30b601 using nl.compay.entities.CompayDAO#b124fa
Persisting: nl.compay.entities.EPayment#ed3b53 using nl.compay.entities.CompayDAO#b124fa
Closing DOA nl.compay.entities.CompayDAO#b124fa
EPayment
package nl.compay.entities;
// Generated 21-mei-2009 12:27:07 by Hibernate Tools 3.2.2.GA
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* Payment generated by hbm2java
*/
#Entity
#Table(name = "payment", catalog = "compay")
public class EPayment implements java.io.Serializable {
private static final long serialVersionUID = -2578493336948256566L;
private Integer id;
private EUser userByToUserId;
private EUser userByFromUserId;
private String description;
private float amount;
private String method;
private Date paydate;
public EPayment() {
}
public EPayment(EUser userByToUserId, EUser userByFromUserId, float amount,
Date paydate) {
this.userByToUserId = userByToUserId;
this.userByFromUserId = userByFromUserId;
this.amount = amount;
this.paydate = paydate;
}
public EPayment(EUser userByToUserId, EUser userByFromUserId,
String description, float amount, String method, Date paydate) {
this.userByToUserId = userByToUserId;
this.userByFromUserId = userByFromUserId;
this.description = description;
this.amount = amount;
this.method = method;
this.paydate = paydate;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "to_user_id", nullable = false)
public EUser getUserByToUserId() {
return this.userByToUserId;
}
public void setUserByToUserId(EUser userByToUserId) {
this.userByToUserId = userByToUserId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "from_user_id", nullable = false)
public EUser getUserByFromUserId() {
return this.userByFromUserId;
}
public void setUserByFromUserId(EUser userByFromUserId) {
this.userByFromUserId = userByFromUserId;
}
#Column(name = "description", length = 1024)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
#Column(name = "amount", nullable = false, precision = 8)
public float getAmount() {
return this.amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
#Column(name = "method", length = 50)
public String getMethod() {
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "paydate", nullable = false, length = 0)
public Date getPaydate() {
return this.paydate;
}
public void setPaydate(Date paydate) {
this.paydate = paydate;
}
}
As Sherkaner mentioned, a save doesn't result in an INSERT or UPDATE directly. You have to flush the session or - better in my opinion - close the unit of work / commit the transaction. You do have transactions?
use #Transactional on your method.....
#Transactional
public void save(Object ent){
.....
.....
}
The program doesn't have to sync with the database right away, have you tried this.em.flush(); somewhere?
Don't think this as bug in Hibernate implementation.This is desired behavior,you would like to have minimum communication with database so Hibernate(or any good ORM framework) will consolidate all your changes and will flush your changes in one go.

JPA remove constraints at run time

I'm deleting entities from a table with a one to many relationship to the same entity (representing node hierarchy). If I make the xincoCoreNodeId relationship a cascade all it works but I don't want that in the real application.
I don't want removing a leaf removing its parent. Is there a way to modify this relationship at run time or disable the constraints so I can delete the whole table contents without getting constraint complains?
package com.bluecubs.xinco.core.server.persistence;
import com.bluecubs.xinco.core.server.AuditedEntityListener;
import com.bluecubs.xinco.core.server.XincoAuditedObject;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.persistence.annotations.PrivateOwned;
/**
*
* #author Javier A. Ortiz Bultrón <javier.ortiz.78#gmail.com>
*/
#Entity
#Table(name = "xinco_core_node")
#EntityListeners(AuditedEntityListener.class)
#NamedQueries({
#NamedQuery(name = "XincoCoreNode.findAll", query = "SELECT x FROM XincoCoreNode x"),
#NamedQuery(name = "XincoCoreNode.findById", query = "SELECT x FROM XincoCoreNode x WHERE x.id = :id"),
#NamedQuery(name = "XincoCoreNode.findByDesignation", query = "SELECT x FROM XincoCoreNode x WHERE x.designation = :designation"),
#NamedQuery(name = "XincoCoreNode.findByStatusNumber", query = "SELECT x FROM XincoCoreNode x WHERE x.statusNumber = :statusNumber")})
public class XincoCoreNode extends XincoAuditedObject implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "id", nullable = false)
private Integer id;
#Basic(optional = false)
#Column(name = "designation", nullable = false, length = 255)
private String designation;
#Basic(optional = false)
#Column(name = "status_number", nullable = false)
private int statusNumber;
#JoinColumn(name = "xinco_core_language_id", referencedColumnName = "id", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private XincoCoreLanguage xincoCoreLanguageId;
#OneToMany(cascade = CascadeType.PERSIST, mappedBy = "xincoCoreNodeId", fetch = FetchType.LAZY)
private List<XincoCoreNode> xincoCoreNodeList;
#JoinColumn(name = "xinco_core_node_id", referencedColumnName = "id")
#PrivateOwned
#ManyToOne(fetch = FetchType.LAZY)
private XincoCoreNode xincoCoreNodeId;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "xincoCoreNodeId", fetch = FetchType.LAZY)
private List<XincoCoreAce> xincoCoreAceList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "xincoCoreNodeId", fetch = FetchType.LAZY)
private List<XincoCoreData> xincoCoreDataList;
public XincoCoreNode() {
}
public XincoCoreNode(Integer id) {
this.id = id;
}
public XincoCoreNode(Integer id, String designation, int statusNumber) {
this.id = id;
this.designation = designation;
this.statusNumber = statusNumber;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public int getStatusNumber() {
return statusNumber;
}
public void setStatusNumber(int statusNumber) {
this.statusNumber = statusNumber;
}
public XincoCoreLanguage getXincoCoreLanguageId() {
return xincoCoreLanguageId;
}
public void setXincoCoreLanguageId(XincoCoreLanguage xincoCoreLanguageId) {
this.xincoCoreLanguageId = xincoCoreLanguageId;
}
public List<XincoCoreNode> getXincoCoreNodeList() {
return xincoCoreNodeList;
}
public void setXincoCoreNodeList(List<XincoCoreNode> xincoCoreNodeList) {
this.xincoCoreNodeList = xincoCoreNodeList;
}
public XincoCoreNode getXincoCoreNodeId() {
return xincoCoreNodeId;
}
public void setXincoCoreNodeId(XincoCoreNode xincoCoreNodeId) {
this.xincoCoreNodeId = xincoCoreNodeId;
}
public List<XincoCoreAce> getXincoCoreAceList() {
return xincoCoreAceList;
}
public void setXincoCoreAceList(List<XincoCoreAce> xincoCoreAceList) {
this.xincoCoreAceList = xincoCoreAceList;
}
public List<XincoCoreData> getXincoCoreDataList() {
return xincoCoreDataList;
}
public void setXincoCoreDataList(List<XincoCoreData> xincoCoreDataList) {
this.xincoCoreDataList = xincoCoreDataList;
}
#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 XincoCoreNode)) {
return false;
}
XincoCoreNode other = (XincoCoreNode) 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 "com.bluecubs.xinco.core.server.persistence.XincoCoreNode[id=" + id + "]";
}
}
If you are using Hibernate, you can use its support for batch processing to delete many rows in a table efficiently. Basically, the query gets translated from HQL to SQL and runs against the database directly. There are limitations with this approach, though. For example, in-memory state won't be updated if you are holding references to any of the affected objects.
I don't know if JPA itself supports batch processing. Probably not. But if you expect to be affecting a lot of rows (hundreds or thousands), then this is one of those cases where ORM is not really the right tool for the job, anyway. It might make more sense to do it in straight SQL or perhaps a stored procedure. Either way, you can isolate the code inside a Data Access Object so that high-level business logic need not care how the operation is implemented.
I ended doing an special case in Java to handle this.
#Override
public void clearTable() {
try {
/**
* All nodes are linked except the root. So we need to start deleting the leaves first.
*/
while (new XincoCoreNodeJpaController().findXincoCoreNodeEntities().size() > 0) {
for (com.bluecubs.xinco.core.server.persistence.XincoCoreNode xcn : getLeaves()) {
new XincoCoreNodeJpaController().destroy(xcn.getId());
}
}
} catch (XincoException ex) {
Logger.getLogger(XincoCoreNodeServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
private Vector<com.bluecubs.xinco.core.server.persistence.XincoCoreNode> getLeaves() throws XincoException {
Vector<com.bluecubs.xinco.core.server.persistence.XincoCoreNode> leaves =
new Vector<com.bluecubs.xinco.core.server.persistence.XincoCoreNode>();
result = XincoDBManager.protectedCreatedQuery("select x from XincoCoreNode x " +
"where x.id not in (select y.xincoCoreNodeId.id from XincoCoreNode y " +
"where y.xincoCoreNodeId is not null)",null,true);
if (result.size() == 0) {
//Check if the root is there
for (Object o : new XincoCoreNodeJpaController().findXincoCoreNodeEntities()) {
leaves.add((com.bluecubs.xinco.core.server.persistence.XincoCoreNode) o);
}
}
for (Object o : result) {
leaves.add((com.bluecubs.xinco.core.server.persistence.XincoCoreNode) o);
}
return leaves;
}

Categories