Creating Hibernate DAO Object Using the Factory Method Step 18
In my prior examples I had you test your database connections within your action class. You do not want to access your database directly from your action class. It is a better design to have a form of abstraction and encapsulation which will access your data source. Therefore, I am going to explain how to set up your hibernate connection using a Data Access Object (DAO) using the factory method. You should remove any access directly to the database in your action class.
DAO:
The DAO object implements the access mechanism required to work with your data source. In this case our data source is the mySQL database. The DAO completely hides the data source implementation details from its clients. The DAO will act as an adaptor between the components and the data source. It is not necessary for any other part of the application to know about the data source.
Factory Method:
One of the goals of object-oriented design is to delegate responsibility among the different objects. This encourages Encapsulation and Delegation which is a key component in object orientation. The solution to forcing Encapsulation is to use the factory method. This also can be used in the singleton pattern which is a design patter that is used to restrict instantiation of a class to one object. This concept is useful when exactly one object is needed to coordinate actions across the system.
In your UserBook project, create a package called com.dao and in that package you should create a class called UserBookDAO.java. The UserBookDAO is the class that will access your database.
Create a package called com.serviceImpl and in that package create a class called UserBookServiceImpl.java and UserBookService.java. The UserBookServiceImpl class will be the implementation and the UserBookService will be the interface.
Create another package called com.serviceFactory and create a class in that package called ServiceFactory.
After you have created your value object mappings, there are some possible issues you might have received.
Possible Issues:
1) failed.org.hibernate.MappingException: entity class not found: Book
This issue is because the mappings need to declare the full package. See below.
2) javax.servlet.ServletException: failed to lazily initialize a collection of role
This issue is because your sets need to say lazy=false.
Here is some more information concerning lazily initialization-
Non-lazy initialization retrieves an object and all of its related objects at load time. This can result in hundreds if not thousands of select statements when retrieving one entity. The problem is compounded when bi-directional relationships are used, often causing entire databases to be loaded during the initial request. Of course one could tediously examine each object relationship and manually remove those most costly, but in the end, we may be losing the ease of use benefit sought in using the ORM tool. The obvious solution is to employ the lazy loading mechanism provided by hibernate. This initialization strategy only loads an object's one-to-many and many-to-many relationships when these fields are accessed. The scenario is practically transparent to the developer and a minimum amount of database requests are made, resulting in major performance gains.
http://www.blogjava.net/vince/archive/2006/11/27/83850.html
Updates:
In this tutorial you need to make sure you have updated the following:
1) Make sure all of your mappings are in the com.vo package and are included in your War file. Make sure your build.xml copies them correctly. See my prior posts for more information.
2) You need to make sure your user.hibernate.cfg.xml file includes all of your mappings:
<mapping resource="com/vo/Users.hbm.xml" />
<mapping resource="com/vo/Book.hbm.xml" />
<mapping resource="com/vo/Bookcategory.hbm.xml" />
3) Make sure you have data in the database to test your system
4) In the Users.hbm.xml file, change the name="Users" to be name="com.vo.Users".
Where it says entity-name="Book", change that to entity-name="com.vo.Book".
Where it says set name="books", change it to:
set name="books" lazy="false"
5) In the Bookcategory.hbm.xml, change the name="com.vo.Bookcategory" and change
one-to-many class="Book" to
one-to-many class="com.vo.Book"
and change
set name="books" to
set name="books" lazy="false"
6) In the Book class change
name="Book" to
name="com.vo.Book" and change
class="Bookcategory" to
class="com.vo.Bookcategory" and change
set name="userses" inverse="false" to
set name="userses" inverse="false" lazy="false"
and change
entity-name="Users" to
entity-name="com.vo.Users"
The below are the particular class information from the new classes you created:
UserBookDAO.java
package com.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import com.util.HibernateUtil;
import com.vo.Book;
import com.vo.Bookcategory;
import com.vo.Users;
public class UserBookDAO {
public List<Book> getBooks()
{
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
List<Book> results=null;
try {
SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
results= sessionFactory.getCurrentSession().createCriteria(
Book.class).list();
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
} catch (RuntimeException re) {
System.out.println("Error In Hibernate getBooks" re.toString());
throw re;
}
return results;
}
public List<Bookcategory> getBookCategory()
{
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
List<Bookcategory> results=null;
try {
SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
results= sessionFactory.getCurrentSession().createCriteria(
Bookcategory.class).list();
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
} catch (RuntimeException re) {
System.out.println("Error In Hibernate getBookCategory" re.toString());
throw re;
}
return results;
}
public List<Users> getUsers()
{
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
List<Users> results=null;
try {
SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
results= sessionFactory.getCurrentSession().createCriteria(
Users.class).list();
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
} catch (RuntimeException re) {
System.out.println("Error In Hibernate getUsers" re.toString());
throw re;
}
return results;
}
public Book getOneBook(String id)
{ //will be completed later
return null;
}
public Users getOneUser(String id)
{
//will be completed later
return null;
}
}
This class will manage the connection to your database. To test your services, we have methods to get a list of books, users and book categories. We will fill in the other methods later.
UserBookServiceImpl.java
package com.serviceImpl;
import java.util.List;
import com.dao.UserBookDAO;
import com.vo.Book;
import com.vo.Bookcategory;
import com.vo.Users;
public class UserBookServiceImpl implements UserBookService{
UserBookDAO dao=new UserBookDAO();
public List getBooks()
{
return dao.getBooks();
}
public List getBookCategory()
{
return dao.getBookCategory();
}
public List getUsers()
{
return dao.getUsers();
}
public Book getOneBook(String id)
{
return dao.getOneBook(id);
}
public Users getOneUser(String id)
{
return dao.getOneUser(id);
}
}
This class will be the layer that will access the DAO object. This will be the class that you use to access the data you will need.
UserBookService.java
package com.serviceImpl;
import java.util.List;
import com.vo.Book;
import com.vo.Bookcategory;
import com.vo.Users;
public interface UserBookService {
public List getBooks();
public List getBookCategory();
public List getUsers();
public Book getOneBook(String id);
public Users getOneUser(String id);
}
This is the interface used by the UserBookServiceImpl class.
ServiceFactory.java
package com.serviceFactory;
import com.serviceImpl.UserBookService;
import com.serviceImpl.UserBookServiceImpl;
public class ServiceFactory {
private static final ServiceFactory serviceFactory=new ServiceFactory();
private ServiceFactory()
{
}
public static ServiceFactory getInstance(){
return serviceFactory;
}
public UserBookService getUserBookService(){
return new UserBookServiceImpl();
}
}
This is the factory class that will be used to instantiate one instance of the service layer. You will always use the factory to retrieve the services when you need to access the database.
UserAction.java to test your connections and service layer.
package com.action;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import com.serviceFactory.ServiceFactory;
import com.serviceImpl.UserBookService;
import com.vo.Book;
import com.vo.Bookcategory;
import com.vo.Users;
public class UserAction extends DispatchAction {
public ActionForward forwardToUser(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
System.out.println("in forwardToUser");
return mapping.findForward("success");
}
public ActionForward setUser(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
UserBookService service = ServiceFactory.getInstance().getUserBookService();
List<User> userList=service.getUsers();
for(Users user:userList)
{
System.out.println("Name of User: "+user.getFirstName()+" "+user.getLastName());
Set userBook=user.getBooks();
ArrayList<Book> userBookList=new ArrayList(userBook);
for(Book userbook:userBookList)
{
System.out.println("The users name of their book "+userbook.getBookName());
System.out.println("The users author of their book "+userbook.getBookAuthor());
}
}
//make sure you insert data using mysqlog into categoryList<Bookcategory> categoryList=service.getBookCategory();
for(Bookcategory category:categoryList)
{
System.out.println("Name of Category: "+category.getCategory());
}
List<Book> bookList=service.getBooks();
for(Book book:bookList)
{
System.out.println("Name of Book: "+book.getBookName());
}
return mapping.findForward("success");
}
}
If you set everything up correctly, visit your local host and submit your form and you should see the list of your data printing out in your eclipse console.
Go to Step 19 to see how to save objects and retrieve individual objects based on the id.
Go To Step 19 Read more...
