Wednesday, September 18, 2013

Web Services and Java Hibernate

This is about how to deal with web services specifically when you create the backend (dealing with database) using webservices. Assume some data to be inserted to the database is send inside json object by calling a webservice in the backend. Then it unwraps the data which is in the json object and insert them to database table via a POJO class. This may not be suitable for a complete beginner anyway it depends.

I will take sample codes from our project in which our vertical was hospital laboratory. I will consider a senario where data of a lab test result is wrapped in a json object and by calling a webservice it is sent from the front end to backend. Then the data is unwrapped and inserted to the relevant data table.

POJO class: Pain Old Java Object. These classes are very simple classes having few attributes and getters and setters for those attributes. They are specially used in frameworks. In out project we have one POJO class for each and every table in the database. So each and every column in the database table is an attribute of the POJO class. Further reading for POJO

Creating a POJO class:

In src folderInside your package(if any. In this example pojo classes are in "core.classes.lab" package) Create a normal java class using anyname(better use a name closely related to the actual database table). Add all the column names as attributes. To generate getters and setters (in eclipse)
-> click on the source code of pojo class at the end of all attributes
-> Select "Source" from main menu
->select "Generate Getters and Setters.."
->Tick all the attributes
-> Select "ok"

Now you code will look like this

package core.classes.lab;

public class Result {

/*
* This class corresponds to db table Result 
 */

int reportID;//primary key
LabOrder orderID;//a foreign key from LabOrder table
        Double chloride;
        Double serumSodium;
String remarks;

public int getReportID() {
return reportID;
}
public void setReportID(int reportID) {
this.reportID = reportID;
}
public LabOrder getOrderID() {
return orderID;
}
public void setOrderID(LabOrder orderID) {
this.orderID = orderID;
}
 public Double getSerumSodium() {
return serumSodium;
}
public void setSerumSodium(Double serumSodium) {
this.serumSodium = serumSodium;
}
public Double getChloride() {
return chloride;
}
public void setChloride(Double chloride) {
this.chloride = chloride;
}
        public String getRemarks() {
return remarks;
}
       public void setRemarks(String remarks) {
this.remarks = remarks;
}
}

Since there is a foreign key from labOrder table, there should be a class LabOrder which represent the labOrder table in the database.

Lets see how to create the corresponding xml mapping file
This mapping file map database table column to each and every attribute of the corresponding POJO class.

<?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="core.classes.lab.Result" table="labTestResult">

<id name="reportID" type="int" column="labTestResult_ReportID">
<generator class="increment" />
</id>

<many-to-one name="orderID" class="core.classes.lab.LabOrder"
not-null="true" cascade="all" unique="true">
<column name="labTestResult_LabOrderID" />
</many-to-one>

                <property name="serumSodium" column="labTestResult_SerumSodium" type="double" />
<property name="chloride" column="labTestResult_Chloride" type="double" />

<property name="remarks" column="labTestResult_Remarks" type="string" />


</class>
</hibernate-mapping>


  • class name: provide it with your package name as given above e.g. packagename.classname
  • table name: exact name as it is appear in the database
  • id tag: used to map the primary key column.
    • name: attribute name as it appears in the class
    • column: column name as it appears in the database table
    • type: data type in java
    • if it is an auto increment field only insert this tag <generator class="increment" /> 
  • one-to-one relationship mapping:
             <many-to-one name="orderID" class="core.classes.lab.LabOrder"
not-null="true" cascade="all" unique="true">
<column name="labTestResult_LabOrderID" />
</many-to-one>

    •   not_null and cascade has the same meaning as in the context of databases             
  • one-to-many relationship mapping: use above tag without  unique="true"
  • properties: maps all the rest of the attributes to columns 
    • name: attribute name as it appears in the class
    • column: column name as it appears in the database table
    • type: data type in java
After this you need to add this mapping file to hibernate.cfg.xml file where you have configured database name,password,host server details, etc
<mapping resource="lib/driver/lab/mappings/labEquipmentUser.hbm.xml" />


Lets see how to create a service class (in our case in a different package "lib.classes.labmodel") to unwrap the json object and feed data to a class object and send it to another class in order to insert them to database table

package lib.classes.labmodel;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import core.classes.lab.Result;//the corresponding POJO class
import lib.driver.lab.driverclasses.ResultServiceDriver;//service driver class
import org.codehaus.jettison.json.JSONObject;

@Path("/testResult")
public class ResultService {

@POST
@Path("/add")
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.APPLICATION_JSON)
public String addReport(JSONObject json) {

/*
* retrieve data from json object and pass it to service driver class
*/

int orderID;

try {

Result result = new Result();//POJO class object

orderID = json.getInt("orderID");//getting data from json

                        //getting relavant data from json and set them to POJO class object
result.setSerumSodium(Double.valueOf(json.getString("serumSodium").toString()));
                        result.setChloride(Double.valueOf(json.getString("chloride").toString()));
result.setRemarks(json.getString("remarks").toString());

/*sending POJO class instance along with the foreign key to service driver class in order to insert to the database table */                              
ResultServiceDriver resultServiceDriver = new ResultServiceDriver();

 resultServiceDriver.insertData(result, orderID);

return "ok";

} catch (Exception e) {
return e.getMessage();
}
}

}


  • @path() : define the path on how to reach to this service 
    • e.g. you need to add "/testResult/add" to the base url when you need to call the service in the browser or in the front end code
  • When calling this service a json object with necessary should be sent as input parameter to this
  • You will get errors since service driver class is not yet created. Just ignore them for the time being


Lets create a service driver class
in our case it is in another package " lib.driver.lab.driverclasses"

package lib.driver.lab.driverclasses;

import org.hibernate.Query;
import org.hibernate.Session;

import core.classes.lab.Result;
import core.classes.lab.SessionFactoryUtil;

public class ResultServiceDriver {

/*
* manupulate data in db table labTestResult
*/

Session session;
        
        //constructor
public ResultServiceDriver() {

session = SessionFactoryUtil.getSessionFactory().openSession();
}

// insert data to db table labTestResult
public void insertData(Result result, int orderID) {

session.beginTransaction();


//  for orderid ,attaching the foreign key POJO object
LabOrder labOrder = (LabOrder) session.get(LabOrder.class, orderID);

result.setOrderID(labOrder); 


session.save( result);//inserting data to the database table

session.getTransaction().commit();//commit transaction

CloseSession();


private void CloseSession() {
// TODO Auto-generated method stub
session.close();
}

}

That's it....
This shows how to insert values. Once you understand the pattern you just need to add methods to update,delete and select data in the driver class. Since this article is already lengthy I'm not gonna explain them here but you can get those details from following website.
http://www.mkyong.com/hibernate/hibernate-query-examples-hql/

Hope this article will be useful for you.










No comments:

Post a Comment