How to create Hibernate Pojo's and hbm files - java

I have two tables
1) test_prefixmaster(CARDNO(Primary key),Name,Department)
2)test_prefixtransactions(CARDNO(FK),PresentDate)
I want to develop an Employee absent report between two given dates range using Spring and Hibernate
Can any one how can I map this one with hibernate with out annotations?
My Query to produce the Employee Absent Results:
SELECT m.CARDNO AS `EmpCode`
, m.NAME AS `EmpName`
, m.DEPARTMENT AS `Department`
, d.dt AS `AbsentDate`
FROM ( SELECT DATE(t.S_DateTime) AS dt
FROM test_prefixtransactions t
WHERE t.S_DateTime >= '2012-11-26'
AND t.S_DateTime < DATE_ADD( '2012-11-26' ,INTERVAL 1 DAY)
GROUP BY DATE(t.S_DateTime)
ORDER BY DATE(t.S_DateTime)
) d
CROSS
JOIN test_prefixmaster m
LEFT
JOIN test_prefixtransactions p
ON p.S_DateTime >= d.dt
AND p.S_DateTime < d.dt + INTERVAL 1 DAY
AND p.CARDNO = m.CARDNO
WHERE p.CARDNO IS NULL
ORDER
BY m.CARDNO
, d.dt;
Note:'d' is The inline view aliased as d gets us a set of "date" values that we are checking. Using the transaction table as a source of these "date" values is a convenient way to do this. Basically, what we are after is a distinct set of DATE values between the two values passed in as arguments
Note:If an Employee is absent, then no record will be inserted into the Transaction table
I've taken my Pojo's like this:
public class Transcations {
private String cardno;
public String getCardno() {
return cardno;
}
public void setCardno(String cardno) {
this.cardno = cardno;
}
}
package Employee.model;
import java.io.Serializable;
public class PrefixMaster implements Serializable {
private static final long serialVersionUID = -5527566248002296042L;
private String empname;
private String empcode;
private String department;
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public String getEmpcode() {
return empcode;
}
public void setEmpcode(String empcode) {
this.empcode = empcode;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}

Mapping for Transcations
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee.model.Transcations "
table="transaction_master">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="cardno" type="string" column="card_no" />
</hibernate-mapping>
Mapping for PrefixMaster
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee.model.PrefixMaster "
table="prefix_master">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="empname" type="string" column="emp_name" />
<property name="empcode" type="string" column="emp_code" />
<property name="department" type="string" column="dept_name" />
</hibernate-mapping>

Related

Hibernate: How to write Join queries including multi levels?

I am trying to write a HQL Query, which is similar to a MySQL Join. Below are my entities. As you can see below I am not using annotations in my Pojos. Instead I am using XML to do the mapping.
Stock
public class Stock implements java.io.Serializable {
private Integer idstock;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Product product;
private int quantity;
private Date dateCreated;
private Date lastUpdated;
public Stock() {
}
public Stock(Product product, int quantity) {
this.product = product;
this.quantity = quantity;
}
public Stock(Product product, int quantity, Date dateCreated, Date lastUpdated) {
this.product = product;
this.quantity = quantity;
this.dateCreated = dateCreated;
this.lastUpdated = lastUpdated;
}
public Integer getIdstock() {
return this.idstock;
}
public void setIdstock(Integer idstock) {
this.idstock = idstock;
}
public Product getProduct() {
return this.product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getQuantity() {
return this.quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Date getDateCreated() {
return this.dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public Date getLastUpdated() {
return this.lastUpdated;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
}
Product
public class Product implements java.io.Serializable {
private Integer idproduct;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private SparePart sparePart;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private VehicleModel vehicleModel;
private double unitPrice;
private String qrcode;
private boolean enable;
private Integer minimumStockLevel;
private Integer stockReorderLevel;
public Product() {
}
public Product(SparePart sparePart, VehicleModel vehicleModel, double unitPrice, String qrcode, boolean enable) {
this.sparePart = sparePart;
this.vehicleModel = vehicleModel;
this.unitPrice = unitPrice;
this.qrcode = qrcode;
this.enable = enable;
}
public Product(SparePart sparePart, VehicleModel vehicleModel, double unitPrice, String qrcode, boolean enable, Integer minimumStockLevel, Integer stockReorderLevel) {
this.sparePart = sparePart;
this.vehicleModel = vehicleModel;
this.unitPrice = unitPrice;
this.qrcode = qrcode;
this.enable = enable;
this.minimumStockLevel = minimumStockLevel;
this.stockReorderLevel = stockReorderLevel;
}
public Integer getIdproduct() {
return this.idproduct;
}
public void setIdproduct(Integer idproduct) {
this.idproduct = idproduct;
}
public SparePart getSparePart() {
return this.sparePart;
}
public void setSparePart(SparePart sparePart) {
this.sparePart = sparePart;
}
public VehicleModel getVehicleModel() {
return this.vehicleModel;
}
public void setVehicleModel(VehicleModel vehicleModel) {
this.vehicleModel = vehicleModel;
}
public double getUnitPrice() {
return this.unitPrice;
}
public void setUnitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
public String getQrcode() {
return this.qrcode;
}
public void setQrcode(String qrcode) {
this.qrcode = qrcode;
}
public boolean getEnable() {
return this.enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public Integer getMinimumStockLevel() {
return this.minimumStockLevel;
}
public void setMinimumStockLevel(Integer minimumStockLevel) {
this.minimumStockLevel = minimumStockLevel;
}
public Integer getStockReorderLevel() {
return this.stockReorderLevel;
}
public void setStockReorderLevel(Integer stockReorderLevel) {
this.stockReorderLevel = stockReorderLevel;
}
}
VehicleModel
public class VehicleModel implements java.io.Serializable {
private Integer idvehicleModel;
private String modelName;
private String code;
private boolean enable;
public VehicleModel() {
}
public VehicleModel(String modelName, boolean enable) {
this.modelName = modelName;
this.enable = enable;
}
public Integer getIdvehicleModel() {
return this.idvehicleModel;
}
public void setIdvehicleModel(Integer idvehicleModel) {
this.idvehicleModel = idvehicleModel;
}
public String getModelName() {
return this.modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public boolean getEnable() {
return this.enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
SparePart
public class SparePart implements java.io.Serializable {
private Integer idsparePart;
private String sparePartName;
private String code;
private boolean enable;
public SparePart() {
}
public SparePart(String sparePartName, boolean enable) {
this.sparePartName = sparePartName;
this.enable = enable;
}
public Integer getIdsparePart() {
return this.idsparePart;
}
public void setIdsparePart(Integer idsparePart) {
this.idsparePart = idsparePart;
}
public String getSparePartName() {
return this.sparePartName;
}
public void setSparePartName(String sparePartName) {
this.sparePartName = sparePartName;
}
public boolean getEnable() {
return this.enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
Here are my XML mappings
Product.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.Product" table="product" catalog="aaa" optimistic-lock="version">
<id name="idproduct" type="java.lang.Integer">
<column name="idproduct" />
<generator class="identity" />
</id>
<many-to-one name="sparePart" class="beans.SparePart" fetch="select">
<column name="idspare_part" not-null="true" />
</many-to-one>
<many-to-one name="vehicleModel" class="beans.VehicleModel" fetch="select">
<column name="idvehicle_model" not-null="true" />
</many-to-one>
<property name="unitPrice" type="double">
<column name="unit_price" precision="22" scale="0" not-null="true">
<comment>This is the central price for a product. This can change according to the market values.</comment>
</column>
</property>
<property name="qrcode" type="string">
<column name="qrcode" length="45" not-null="true" />
</property>
<property name="enable" type="boolean">
<column name="enable" not-null="true" />
</property>
<property name="minimumStockLevel" type="java.lang.Integer">
<column name="minimum_stock_level" />
</property>
<property name="stockReorderLevel" type="java.lang.Integer">
<column name="stock_reorder_level" />
</property>
</class>
</hibernate-mapping>
Stock.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.Stock" table="stock" catalog="aaa" optimistic-lock="version">
<id name="idstock" type="java.lang.Integer">
<column name="idstock" />
<generator class="identity" />
</id>
<many-to-one name="product" class="beans.Product" fetch="select">
<column name="idproduct" not-null="true" />
</many-to-one>
<property name="quantity" type="int">
<column name="quantity" not-null="true" />
</property>
<property name="dateCreated" type="timestamp">
<column name="date_created" length="0" />
</property>
<property name="lastUpdated" type="timestamp">
<column name="last_updated" length="0" />
</property>
</class>
</hibernate-mapping>
SparePart.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.SparePart" table="spare_part" catalog="aaa" optimistic-lock="version">
<id name="idsparePart" type="java.lang.Integer">
<column name="idspare_part" />
<generator class="identity" />
</id>
<property name="sparePartName" type="string">
<column name="spare_part_name" length="100" not-null="true" />
</property>
<property name="code" type="string">
<column name="code" length="100"/>
</property>
<property name="enable" type="boolean">
<column name="enable" not-null="true" />
</property>
</class>
</hibernate-mapping>
VehicleModel.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.VehicleModel" table="vehicle_model" catalog="aaa" optimistic-lock="version">
<id name="idvehicleModel" type="java.lang.Integer">
<column name="idvehicle_model" />
<generator class="identity" />
</id>
<property name="modelName" type="string">
<column name="model_name" length="100" not-null="true" />
</property>
<property name="code" type="string">
<column name="code" length="100"/>
</property>
<property name="enable" type="boolean">
<column name="enable" not-null="true" />
</property>
</class>
</hibernate-mapping>
Right now I have the following query.
public List<Stock> getAllStock(Session session) {
Query query = session.createQuery("FROM Stock s");
List<Stock> list = (List<Stock>) query.list();
return list;
}
This gives me,
Stock
Product of each Stock
SparePart of each Product
VehicleModel of each Product
However this is extremely slow due to the famous n+1 issue. To get data from each table, this code generated a SQL query, resulting huge amount of sql queries. The more data you have, the more queries this generates . As a result, this is a super slow process. Currently it takes 40 seconds.
Instead I need to write HQL joins and get data with a single SQL query. How can I do this?
You should use JOIN FETCH to tell JPA/Hibernate that that it should load it.
From the Hibernate docs:
If you forget to JOIN FETCH all EAGER associations, Hibernate is going
to issue a secondary select for each and every one of those which, in
turn, can lead to N+1 query issues.
For this reason, you should prefer LAZY associations.
select s from Stock s join fetch s.product p
join fetch p.sparePart sp
join fetch p.vehicleModel v
Please also read the documentation: https://docs.jboss.org/hibernate/orm/5.5/userguide/html_single/Hibernate_User_Guide.html#best-practices-fetching-associations
You can use criteria implementation of hibernate and using alias you can join
Below is some reference code that may help
Criteria c = session.createCriteria(Stock.class, "stock");
c.createAlias("stock.product", "product");//it is like inner join
c.createAlias("product.spare_part","spare_part");
c.createAlias("product.vehicle_model","vehicle_model");
return c.list();

Select and order list by other condition(Criteria inner join hibernate)

Supposing that we create 2 tables with below SQL :
create table Supplier (id int, name VARCHAR, count int);
create table Product (id int, name VARCHAR, description VARCHAR, price double, supplierId int);
Models:
public class Supplier {
private int id;
private String name;
private int count;
public int getId(){ return id;}
public void setId(int id){ this.id = id; }
public String getName(){ return name;}
public void setName(String name){ this.name = name;}
public int getCount() { return count;}
public void setCount(int count) { this.count = count;}
}
AND
public class Product {
private int id;
private String name;
private String description;
private Double price;
private Supplier supplier;
public int getId() { return id;}
public void setId(int id) { this.id = id; }
public String getName() { return name;}
public void setName(String name) { this.name = name;}
public String getDescription() { return description;}
public void setDescription(String description) { this.description = description; }
public Double getPrice() {return price;}
public void setPrice(Double price) { this.price = price;}
#OneToOne(targetEntity=ProductAssignment.class, mappedBy = "supplierId", fetch = FetchType.LAZY)
public Supplier getSupplier() { return supplier;}
public void setSupplier(Supplier supplier) { this.supplier = supplier; }
}
If I want to select all products order by count in supplier I can use the below code :
Criteria crit = session.createCriteria(Product.class);
Criteria critSupplier = crit.createCriteria("supplier");
critSupplier.addOrder(Order.desc("count"));
But now, I want to select all suppliers order by price in Product table.
if I want to use MySQL, the below is the script:
select * from supplier s inner join product p ON s.id = p.supplierId order by p.price
Now I want to transfer this SQL into Hibernate Criteria query in java code?
Please help me in this case?
Here you have a bidirectional relationship between two models: Supplier and Product. It is a bidirectional relationship since you want both the models to be aware of each other, and recollect each other information, based on the link that joins them (supplierId). The relationship is also a one(Supplier)-toMany(Products)
So, first off, you are missing the fact that also Supplier must be aware of the existence of the relationship. You have to express this "awareness" by modifying the Supplier model and add to it the list products:
public class Supplier implements Serializable{
private int id;
private String name;
private int count;
private List<Product> products;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
#Override
public String toString() {
return "Supplier{" + "name=" + name + '}';
}
The second step is to communicate the ORM(in your case hibernate) the relationship between your two models. Online you can find plenty of documentation that explains this subtle "step" of hibernate. in your case, something like this should do.
Hibernate mapping of Supplier:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xxx.stackoverflowdb.model.Supplier" table="Supplier">
<id column="id" name="id" type="int">
<generator class="assigned"/>
</id>
<property column="name" name="name" type="string"/>
<property column="count" name="count" type="int"/>
<bag name="products" table="product" inverse="true" lazy="false" fetch="select">
<key>
<column name="id"/>
</key>
<one-to-many class="com.xxx.stackoverflowdb.model.Product"/>
</bag>
</class>
</hibernate-mapping>
Hibernate mapping of Product:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xxx.stackoverflowdb.model.Product" table="PRODUCT">
<id column="id" name="id" type="int">
<generator class="assigned"/>
</id>
<property column="name" name="name" type="string"/>
<property column="description" name="description" type="string"/>
<property column="price" name="price" type="double"/>
<many-to-one name="supplierId" class="com.xxx.stackoverflowdb.model.Supplier" column="supplierId" insert="false" update="false" lazy="false"/>
</class>
</hibernate-mapping>
As you can see, both mapping files declare the relationship. With this set, you can write the Criteria and have it do the job. Since it now hibernate knows about the relationship, it can help you. I've created a simple tester class that demonstrates it:
public class Tester {
public static void main(String[] args) {
//gets a session, assuming your cg file is in a folder called hibernate_dispatcher
//under classpath
SessionFactory sessionFactory = new Configuration().configure("/hibernate_dispatcher/hibernate.cfg.xml")
.buildSessionFactory();
Session session = sessionFactory.openSession();
//gets a session, assuming your cg file is in a folder called hibernate_dispatcher
//under classpath
//YOUR own query --> gets all products order by count in supplier
Criteria criteria1 = session.createCriteria(Product.class);
criteria1.createAlias("supplierId", "supp");
criteria1.addOrder(Order.desc("supp.count"));
for(Object p:criteria1.list()){
Product nthP=(Product)p;
System.out.println(nthP);
}
//YOUR own query --> gets all products order by count in supplier
//the query you've asked --> gets all products order by price in Product
Criteria criteria2 = session.createCriteria(Supplier.class);
criteria2.createAlias("products", "prod");
criteria2.addOrder(Order.desc("prod.price"));
for(Object s:criteria2.list()){
Supplier nthS=(Supplier)s;
System.out.println(nthS);
}
//the query you've asked --> gets all products order by price in Product
}
}

Hibernate- failed to lazily initialize a collection of role: beans.Language.patients, could not initialize proxy - no Session

I use hibernate to create a rest api. I create a method to get all items in a table.
public List<Language> getAllLanguages(Session session) {
List<Language> languages=(List<Language>)session.createQuery("from Language").list();
return languages;
}
This is my Language.java
public class Language implements java.io.Serializable {
private Integer idlanguage;
private String language;
private Set<Patient> patients = new HashSet<Patient>(0);
public Language() {
}
public Language(String language) {
this.language = language;
}
public Language(String language, Set<Patient> patients) {
this.language = language;
this.patients = patients;
}
public Integer getIdlanguage() {
return this.idlanguage;
}
public void setIdlanguage(Integer idlanguage) {
this.idlanguage = idlanguage;
}
public String getLanguage() {
return this.language;
}
public void setLanguage(String language) {
this.language = language;
}
public Set<Patient> getPatients() {
return this.patients;
}
public void setPatients(Set<Patient> patients) {
this.patients = patients;
}
}
And this is my Patient.java
// Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1
import beans.DiabetesType;
import beans.Illness;
import beans.Language;
import beans.Reminder;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* Patient generated by hbm2java
*/
public class Patient implements java.io.Serializable {
private Integer idpatient;
private DiabetesType diabetesType;
private Language language;
private String customId;
private String diabetesOther;
private String firstName;
private String lastName;
private String userName;
private String password;
private Date dateCreated;
private Date lastUpdated;
private Set<Illness> illnesses = new HashSet<Illness>(0);
private Set<Reminder> reminders = new HashSet<Reminder>(0);
public Patient() {
}
public Patient(Integer idpatient, String password) {
this.idpatient = idpatient;
this.password = password;
}
public Patient(DiabetesType diabetesType, Language language, String customId, String firstName, String userName, String password, Date lastUpdated) {
this.diabetesType = diabetesType;
this.language = language;
this.customId = customId;
this.firstName = firstName;
this.userName = userName;
this.password = password;
this.lastUpdated = lastUpdated;
}
public Patient(DiabetesType diabetesType, Language language, String customId, String diabetesOther, String firstName, String lastName, String userName, String password, Date dateCreated, Date lastUpdated, Set<Illness> illnesses, Set<Reminder> reminders) {
this.diabetesType = diabetesType;
this.language = language;
this.customId = customId;
this.diabetesOther = diabetesOther;
this.firstName = firstName;
this.lastName = lastName;
this.userName = userName;
this.password = password;
this.dateCreated = dateCreated;
this.lastUpdated = lastUpdated;
this.illnesses = illnesses;
this.reminders = reminders;
}
public Integer getIdpatient() {
return this.idpatient;
}
public void setIdpatient(Integer idpatient) {
this.idpatient = idpatient;
}
public DiabetesType getDiabetesType() {
return this.diabetesType;
}
public void setDiabetesType(DiabetesType diabetesType) {
this.diabetesType = diabetesType;
}
public Language getLanguage() {
return this.language;
}
public void setLanguage(Language language) {
this.language = language;
}
public String getCustomId() {
return this.customId;
}
public void setCustomId(String customId) {
this.customId = customId;
}
public String getDiabetesOther() {
return this.diabetesOther;
}
public void setDiabetesOther(String diabetesOther) {
this.diabetesOther = diabetesOther;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getUserName() {
return this.userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getDateCreated() {
return this.dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public Date getLastUpdated() {
return this.lastUpdated;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public Set<Illness> getIllnesses() {
return this.illnesses;
}
public void setIllnesses(Set<Illness> illnesses) {
this.illnesses = illnesses;
}
public Set<Reminder> getReminders() {
return this.reminders;
}
public void setReminders(Set<Reminder> reminders) {
this.reminders = reminders;
}
}
Important: The beans and mappings are reverse engineered from MySQL database, via NetBeans. I do not need to get any data related to patient when calling getAllLangauges. My language table has only 2 columns, idlanguage and language. Patient table has a foriegn key of language table
Before using this method in rest api , it worked perfectly without any exception. But when I used this in rest api, it created a complexity in there.
I am not using annotations in here. I used hibernate reverse engineering wizard to map above entities . This is my rest api method.
#Path("/language")
public class LanguageJSONService {
#GET
#Path("/getAllLanguages")
#Produces(MediaType.APPLICATION_JSON)
public List<Language> getAllLanguages(){
LanguageService languageService=new LanguageService();
List<Language> list = languageService.getAllLanguages();
return list;
}
}
This is the way how I call the method,
Client client = ClientBuilder.newClient();
List<Language> list = client.target("http://localhost:8080/simple_rest/rest")
.path("/language/getAllLanguages")
.request(MediaType.APPLICATION_JSON)
.get(new GenericType<List<Language>>() {
});
for (int i = 0; i < list.size(); i++) {
System.out.println("Id - " + list.get(i).getIdlanguage() + " Language - " + list.get(i).getLanguage());
}
When I call the method ,
failed to lazily initialize a collection of role: beans.Language.patients, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->beans.Language["patients"])
is occurred.
Interestingly, if I did not close the session, then I get an output like below which is totally something else, seems like it is trying to display its foreign key tables and their foreign key tables and so on...
[{"idlanguage":1,"language":"English","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":
[{"idpatient":1,"diabetesType":
Have any ideas about this problem ?
Update
my configuration file
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="show_sql">true</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/*****</property>
<property name="hibernate.connection.username">*****</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">3000</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<property name="hibernate.c3p0.preferredTestQuery">SELECT 1</property>
<property name="hibernate.connection.password">************</property>
<mapping resource="beans/Reminder.hbm.xml"/>
<mapping resource="beans/Food.hbm.xml"/>
<mapping resource="beans/Patient.hbm.xml"/>
<mapping resource="beans/Illness.hbm.xml"/>
<mapping resource="beans/Language.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Language.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.Language" table="language" catalog="myglukose" optimistic-lock="version">
<id name="idlanguage" type="java.lang.Integer">
<column name="idlanguage" />
<generator class="identity" />
</id>
<property name="language" type="string">
<column name="language" length="45" not-null="true" />
</property>
<set name="patients" table="patient" inverse="true" lazy="true" fetch="select">
<key>
<column name="language_idlanguage" not-null="true" />
</key>
<one-to-many class="beans.Patient" />
</set>
</class>
</hibernate-mapping>
This is my patient mapping file,
Patient.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.Patient" table="patient" catalog="myglukose" optimistic-lock="version">
<id name="idpatient" type="java.lang.Integer">
<column name="idpatient" />
<generator class="identity" />
</id>
<many-to-one name="diabetesType" class="beans.DiabetesType" fetch="select">
<column name="diabetes_type_iddiabetes_type" not-null="true" />
</many-to-one>
<many-to-one name="language" class="beans.Language" fetch="select">
<column name="language_idlanguage" not-null="true" />
</many-to-one>
<property name="customId" type="string">
<column name="custom_id" length="45" not-null="true" />
</property>
<property name="diabetesOther" type="string">
<column name="diabetes_other" length="45" />
</property>
<property name="firstName" type="string">
<column name="first_name" length="100" not-null="true" />
</property>
<property name="lastName" type="string">
<column name="last_name" length="100" />
</property>
<property name="userName" type="string">
<column name="user_name" length="45" not-null="true" />
</property>
<property name="password" type="string">
<column name="password" length="45" not-null="true" />
</property>
<property name="dateCreated" type="timestamp">
<column name="date_created" length="19" />
</property>
<property name="lastUpdated" type="timestamp">
<column name="last_updated" length="19" not-null="true">
<comment>Stores the basic information of the patient</comment>
</column>
</property>
<set name="illnesses" table="illness" inverse="true" lazy="true" fetch="select">
<key>
<column name="patient_idpatient" not-null="true" />
</key>
<one-to-many class="beans.Illness" />
</set>
<set name="reminders" table="reminder" inverse="true" lazy="true" fetch="select">
<key>
<column name="patient_idpatient" not-null="true" />
</key>
<one-to-many class="beans.Reminder" />
</set>
</class>
</hibernate-mapping>
Your json converter tries to serialize the whole entity, which contains the list of all patients speaking each language. From what i understood, the list of patient in the json is not expected. So you have three options (ordered in which i would consider them) :
Remove the mapping to patients in Language entity. Do you need to get acces
s to patients from the language entity ? If not remove this mapping.
Create a Language DTO where you transfer your data before exiting the tx layer. This way whoever calls the service will never get a LazyInitException. No surprise : DTO fields are always set eagerly.
Configure your json converter to not serialize the patient fields. You've not said which json lib you're using. Some of them give you an annotation to ignore some fields (#JsonIgnore for Jackson for example), other requires java configuration.
To apply the first solution, update those files this way :
Language.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.Language" table="language" catalog="myglukose" optimistic-lock="version">
<id name="idlanguage" type="java.lang.Integer">
<column name="idlanguage" />
<generator class="identity" />
</id>
<property name="language" type="string">
<column name="language" length="45" not-null="true" />
</property>
</class>
</hibernate-mapping>
Language.java
public class Language implements java.io.Serializable {
private Integer idlanguage;
private String language;
protected Language() {
}
public Language(String language) {
this.language = language;
}
public Integer getIdlanguage() {
return this.idlanguage;
}
protected void setIdlanguage(Integer idlanguage) {
this.idlanguage = idlanguage;
}
public String getLanguage() {
return this.language;
}
public void setLanguage(String language) {
this.language = language;
}
}
I've updated the no-arg constructor and setId method to protected. You can even update them to private : only hibernate should ever use them (and it can use private fields / methods).
When you try to access a lazy field you need to do that before the session of hibernate is closed.
When you exit from the context of the session is not possible for hibernate to access the database if needed, so a LazyInitializationException is thrown.
From javadoc:
Indicates access to unfetched data outside of a session context. For example, when an uninitialized proxy or collection is accessed after the session was closed.
From current explanation I am not able to see you are doing like : language.getPatients();
But if you are writing HQL query to access all patients form Language Entity then I think you should use join . As i can see the exception if related to LazyInitializationException in beans.Language.patients.
so i will suggest below code ...Check if it usefull to you or not..
public List<Language> getAllLanguages(Session session) {
List<Language> languages=(List<Language>)session.createQuery("from Language as l JOIN l.patients").list();
return languages;
}

How to handle database null values in Hibernate Application?

I am getting " org.hibernate.PropertyAccessException" due to null values in my database table. How to handle the exception?
My files are
FetchTest.java
package com.raj.java.hiberanteDemos;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class FetchTest {
public static void main(String[] args) {
Configuration cfg=new Configuration().configure("hibernate.cfg.xml");
SessionFactory factory=cfg.buildSessionFactory();
Session session1=factory.openSession();
Employee emp1=(Employee)session1.get(Employee.class,7839);
System.out.println(emp1.getEmpno()+" "+emp1.getEname()+" "+emp1.getSal());
session1.close();
Session session2=factory.openSession();
Employee emp2=(Employee)session2.load(Employee.class,7839);
System.out.println(emp2.getEmpno()+" "+emp2.getEname()+" "+emp2.getSal());
session2.close();
}
}
Employee.java
package com.raj.java.hiberanteDemos;
import java.sql.Date;
class Employee {
private int empno, mgr, deptnumber;
private String ename, job;
private double sal, comm;
private Date hiredate;
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public int getDeptnumber() {
return deptnumber;
}
public void setDeptnumber(int deptnumber) {
this.deptnumber = deptnumber;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public double getComm() {
return comm;
}
public void setComm(double comm) {
this.comm = comm;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
}
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect
</property>
<property name="connection.url">someValidurl</property>
<property name="connection.username">username</property>
<property name="connection.password">password</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.show_sql">true</property>
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<mapping resource="employee.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
employee.hbm.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- <class name="com.javatpoint.mypackage.Employee" table="employee"> <id
name="empid"> <generator class="assigned"></generator> </id> <property name="firstName"></property>
<property name="lastName"></property> </class> -->
<class name="com.raj.java.hiberanteDemos.Employee" table="emp">
<id name="empno" type="int" column="EMPNO">
<generator class="increment" />
</id>
<property name="ename" type="java.lang.String" />
<property name="mgr" type="int" />
<property name="deptnumber" type="int" column="deptno" />
<property name="job" type="java.lang.String" />
<property name="sal" type="double" />
<property name="comm" type="double" />
<property name="hiredate" type="java.sql.Date" />
</class>
</hibernate-mapping>
When I ran this application I am getting below error message.
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select employee0_.EMPNO as EMPNO0_0_, employee0_.ename as ename0_0_, employee0_.mgr as mgr0_0_, employee0_.deptno as deptno0_0_, employee0_.job as job0_0_, employee0_.sal as sal0_0_, employee0_.comm as comm0_0_, employee0_.hiredate as hiredate0_0_ from emp employee0_ where employee0_.EMPNO=?
Exception in thread "main" org.hibernate.PropertyAccessException: exception setting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) setter of com.raj.java.hiberanteDemos.Employee.setMgr
at org.hibernate.tuple.PojoEntityTuplizer.setPropertyValuesWithOptimizer(PojoEntityTuplizer.java:215)
at org.hibernate.tuple.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:185)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3232)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:129)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:842)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:47)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:41)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:177)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:862)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:799)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:792)
at com.raj.java.hiberanteDemos.FetchTest.main(FetchTest.java:13)
Caused by: net.sf.cglib.beans.BulkBeanException
at com.raj.java.hiberanteDemos.Employee$$BulkBeanByCGLIB$$142cfd75.setPropertyValues(<generated>)
at org.hibernate.tuple.PojoEntityTuplizer.setPropertyValuesWithOptimizer(PojoEntityTuplizer.java:212)
... 19 more
Caused by: java.lang.NullPointerException
... 21 more
my emp table data
when I update all the null values with 0 or some other values its working fine.
Please help me in solving the error without updating null values in database table.
Thanks in Advance,
Raj
I would personally recommend to actually "clean" the database values, maybe setting the column not nullable.
But if this can't be done, what you can do is modify your setters, so that it checks for null:
public void setComm(Double comm) {
if(null != comm){
this.comm = comm;
}else{
this.comm = 0;
}
}
hope this helps
Your mgr-Property is int, which does not allow null. Change it to Integer, which allows null. Or make a default value for your mgr column.
The best way to avoid Hibernate's attempts at setting null values to primitives is to use Wrapper classes (Integer, Long, Double...); and especially, if you need to tack on a column or 2 to an existing table. Auto-boxing is your friend.

Hibernate many-to-many mapping not saved in pivot table

I having problems saving many to many relationships to a pivot table.
The way the pojos are created is unfortunately a pretty long process which spans over a couple of different threads which work on the (to this point un-saved) object until it is finally persisted. I associate the related objects to one another right after they are created and when debugging I can see the List of related object populated with their respective objects. So basically all is fine to this point. When I persist the object everything get saved except the relations in the pivot table.
mapping files:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.thebeansgroup.jwinston.plugin.orm.hibernate.object">
<class name="ShowObject" table="show_object">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<set cascade="all" inverse="true" name="venues" table="venue_show">
<key column="show_id"/>
<many-to-many class="VenueObject"/>
</set>
</class>
</hibernate-mapping>
and the other
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.thebeansgroup.jwinston.plugin.orm.hibernate.object">
<class name="VenueObject" table="venue_object">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="latitude" type="integer"/>
<property name="longitude" type="integer"/>
<set cascade="all" inverse="true" name="shows" table="venue_show">
<key column="venue_id"/>
<many-to-many class="ShowObject"/>
</set>
</class>
</hibernate-mapping>
pojos:
public class ShowObject extends OrmObject
{
private Long id;
private String name;
private Set venues;
public ShowObject()
{
}
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;
}
public Set getVenues()
{
return venues;
}
public void setVenues(Set venues)
{
this.venues = venues;
}
}
and the other:
public class VenueObject extends OrmObject
{
private Long id;
private String name;
private int latitude;
private int longitude;
private Set shows = new HashSet();
public VenueObject()
{
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public int getLatitude()
{
return latitude;
}
public void setLatitude(int latitude)
{
this.latitude = latitude;
}
public int getLongitude()
{
return longitude;
}
public void setLongitude(int longitude)
{
this.longitude = longitude;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Set getShows()
{
return shows;
}
public void setShows(Set shows)
{
this.shows = shows;
}
}
Might the problem be related to the lack of annotations?
Couple things to try:
You have inverse="true" on both ends of many-to-many. It should be only at one end.
Make your sets not lazy.
You didn't specify column property for many-to-many tag.
So it should look something like this at the end:
<class name="ShowObject" table="show_object">
...
<set lazy="false" cascade="all" name="venues" table="venue_show">
<key column="show_id"/>
<many-to-many class="VenueObject" column="venue_id" />
</set>
</class>
<class name="VenueObject" table="venue_object">
...
<set lazy="false" cascade="all" inverse="true" name="shows" table="venue_show">
<key column="venue_id"/>
<many-to-many class="ShowObject" column="show_id"/>
</set>
</class>

Categories

Resources