I am using Spring, Hibernate and Struts2 for my Java web application. I have created DAOs, Services for Some tables in the database and I am able to process with that in my Action class. Now I want to populate a <select> option in my JSP page to display one table contents.
But the problem is, Select box is in index.jsp, That is it should display the options when the application is loading(before calling any action classes).
I don't know how to use hibernate in JSP to get data. If it was in other JSP pages, I could have done that by using Action class before the other JSP page loads.
Entity Bean
#Entity
#Table(name = "AAI_SubjectArea")
public class AAISubjectArea {
private String aAIColumnName;
private String aAISubjectAreaName;
private String aAISubjectAreaDes;
private String aAITableName;
//Getters and setters
Service Interface
public interface IAAISubjectAreaService {
public List<AAISubjectArea> getAllAAISubjectArea();
}
DAO Interface
public interface IAAISubjectAreaDao {
public List<AAISubjectArea> getAllAAISubjectArea();
}
Service Implementation
public class AAISubjectAreaServiceImpl implements IAAISubjectAreaService{
#Autowired
private IAAISubjectAreaDao aAISubjectAreaDao;
public void setAAISubjectAreaDao(IAAISubjectAreaDao aAISubjectAreaDao) {
this.aAISubjectAreaDao= aAISubjectAreaDao;
}
#Override
public List<AAISubjectArea> getAllAAISubjectArea(){
return ref_LookUpDao.getAllAAISubjectArea();
}
}
DAO Implementation
public class AAISubjectAreaDaoImpl implements IAAISubjectAreaDao{
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getSession() {
Session session = sessionFactory.openSession();
return session;
}
private int BATCH_SIZE = 50;
#Override
public List<AAISubjectArea> getAllAAISubjectArea(){
String queryString = "from AAISubjectArea as aAISubjectArea";
Session session = getSession();
Query query = session.createQuery(queryString);
List<AAISubjectArea> aAISubjectAreaList = query.list();
return aAISubjectAreaList;
}
}
Here is a Test Case which is working fine.
public class SubjectAreaTestCase extends BaseDAOTest{
#Autowired
IAAISubjectAreaDao aAISubjectAreaService;
#Test
public void testGetIAISubjectArea() {
List listAppType = aAISubjectAreaService.getAllAAISubjectArea();
System.out.println(listAppType.size());
}
}
Related
I want to understand how can i implement the generic methods like add, edit, delete and search on my database, i have already made the connection (hibernate) and works fine
I do have this method, that works
Class: GenericDAO
public <T> T save(final T o){
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
Object object = (T) session.save(o);
trans.commit();
return (T) object;
}
and in Main
GenericDAO gen = new GenericDAO();
gen.save(object);
also i have others methods that i dont know how to use them
Class: GenericDAO
public void delete(final Object object){
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
session.delete(object);
trans.commit();
}
/***/
public <T> T get(final Class<T> type, final int id){
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
Object object = (T) session.get(type, id);
trans.commit();
return (T) object;
}
public <T> List<T> getAll(final Class<T> type) {
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction trans=session.beginTransaction();
final Criteria crit = session.createCriteria(type);
List<T> list = crit.list();
trans.commit();
return list;
}
Thank you
I think GenericDAO class is base class. It's not for using directly. Did you check this article ? I checked this article and created a sample project.
Don't repeat the DAO!
Example
GitHub - generic-dao-hibernate sample
For example, you might want to create an API to retrieve all employees list according to MySQL first step example.
Employees table schema is like following:
Base SQL
CREATE TABLE employees (
emp_no INT NOT NULL, -- UNSIGNED AUTO_INCREMENT??
birth_date DATE NOT NULL,
first_name VARCHAR(14) NOT NULL,
last_name VARCHAR(16) NOT NULL,
gender ENUM ('M','F') NOT NULL, -- Enumeration of either 'M' or 'F'
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no) -- Index built automatically on primary-key column
-- INDEX (first_name)
-- INDEX (last_name)
);
O/R Mapping
Hibernate require you to configure mapping object-relation settings. After that, you will enjoy converting object-to-sql and sql-to-object.
Entity class based on SQL
#Entity, #Table, #Id, #Column, #GeneratedValue are from Hibernate
#Data, #NoArgsConstructor are from lombok, it reduces getter/setter code
#XmlRootElement, #XmlAccessorType are from jaxb, you might don't need to use it
#Entity
#Data
#NoArgsConstructor
#Table(name = "employees")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement
public class Employees implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "emp_no", unique = true)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer empNo;
#Column(name = "birth_date")
private Date birthDate;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "gender")
#Enumerated(EnumType.STRING)
private Gender gender;
#Column(name = "hire_date")
private Date hireDate;
}
Resource Class for Frontend
You always need to write DAO(Data Access Object) for accessing the database. GenericDAO is a method to reduce boilerplate sources codes.
EmployeesResource class
CRUD operations on WEB API
#create, #read, #update or #delete
should be equivalent with
SQL
INSERT, SELECT, UPDATE and DELETE
You need to identify a record or records with key. In this case, id is sample primary key.
#Path("/employee")
public class EmployeesResource {
static Logger log = LoggerFactory.getLogger(EmployeesResource.class);
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Employees> index(#BeanParam Employees paramBean) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
List<Employees> result = dao.read();
System.out.println("Get all employees: size = " + result.size());
return result;
}
#GET
#Path("{id}")
#Produces(MediaType.APPLICATION_JSON)
public Employees show(#PathParam("id") Integer id) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
System.out.println("Get employees -> id = " + id);
return dao.read(id);
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Integer create(Employees obj) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
return dao.create(obj);
}
#PUT
#Path("{id}")
#Consumes(MediaType.APPLICATION_JSON)
public void update(Employees obj, #PathParam("id") String id) {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("employeesDao");
dao.update(obj);
}
#DELETE
#Path("{id}")
public void destroy(#PathParam("id") Integer id) throws Exception {
EmployeesDao dao = (EmployeesDao) SpringApplicationContext.getBean("EmployeesDao");
dao.delete(id);
}
}
GenericDao interface & implementation
Interface ( as is from ibm's post )
According to the post, we can declare dao interface. Then we should implement that interface's methods.
public interface GenericDao<T, PK extends Serializable> {
/** Persist the newInstance object into database */
PK create(T newInstance);
/**
* Retrieve an object that was previously persisted to the database using
* the indicated id as primary key
*/
T read(PK id);
List<T> read();
/** Save changes made to a persistent object. */
void update(T transientObject);
/** Remove an object from persistent storage in the database */
void delete(PK id) throws Exception;
void delete(T persistentObject) throws Exception;
}
Implementation
public class GenericDaoHibernateImpl<T, PK extends Serializable> implements GenericDao<T, PK> {
private Class<T> type;
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public GenericDaoHibernateImpl(Class<T> type) {
this.type = type;
}
// Not showing implementations of getSession() and setSessionFactory()
private Session getSession() {
Session session = sessionFactory.getCurrentSession();
return session;
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public PK create(T o) {
return (PK) getSession().save(o);
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public void update(T o) {
getSession().update(o);
}
#Transactional(readOnly = true)
public T read(PK id) {
return (T) getSession().get(type, id);
}
#SuppressWarnings("unchecked")
#Transactional(readOnly = true)
public List<T> read() {
return (List<T>) getSession().createCriteria(type).list();
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public void delete(PK id) {
T o = getSession().load(type, id);
getSession().delete(o);
}
#Transactional(readOnly = false, rollbackFor = RuntimeException.class)
public void delete(T o) {
getSession().delete(o);
}
If you use only simple CRUD operations in the project, you don't need to append any code for SQL operations. For example, you can create another simple SQL tables like divisions_table or personnel_table with using extends GenericDao<Division, Integer> or extends GenericDao<Personnel, Integer>.
EDIT
To instantiate real dao class related with each table, you need to configure applicationContext.xml and beans.
example
<bean id="employeesDao" parent="abstractDao">
<!-- You need to configure the interface for Dao -->
<property name="proxyInterfaces">
<value>jp.gr.java_conf.hangedman.dao.EmployeesDao</value>
</property>
<property name="target">
<bean parent="abstractDaoTarget">
<constructor-arg>
<value>jp.gr.java_conf.hangedman.models.Employees</value>
</constructor-arg>
</bean>
</property>
</bean>
P.S.
You need to remember this article was written a decade ago. And, you should think seriously about which O/R mapper is really good or not. I think O/R mapper is slightly declining now. Instead of Hibernate, you can find MyBatis , JOOQ
This is one way to implement a hibernate centric generic DAO. It provides basic CRUD operations along with simple search but can be extended to include other generic features.
IGenericDAO interface
public interface IGenericDAO<T extends Serializable> {
T findOne(long id);
List<T> findAll();
void create(T entity);
void update(T entity);
void delete(T entity);
void deleteById(long entityId);
public void setClazz(Class<T> clazzToSet);
}
AbstractTemplateDAO
import java.io.Serializable;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class AbstractHibernateDAO<T extends Serializable> implements IGenericDAO<T> {
private Class<T> clazz;
#Autowired
SessionFactory sessionFactory;
public final void setClazz(Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
#Override
public T findOne(long id) {
return (T) getCurrentSession().get(clazz, id);
}
#Override
public List<T> findAll() {
return getCurrentSession().createQuery("from " + clazz.getName(),clazz).getResultList();
}
#Override
public void create(T entity) {
getCurrentSession().persist(entity);
}
#Override
public void update(T entity) {
getCurrentSession().merge(entity);
}
#Override
public void delete(T entity) {
getCurrentSession().delete(entity);
}
#Override
public void deleteById(long entityId) {
T entity = findOne(entityId);
delete(entity);
}
protected final Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
GenericHiberateDAO
Note: the use of scope prototype here. The spring container creates a new instance of the dao on each request.
#Repository
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GenericHibernateDAO<T extends Serializable> extends AbstractHibernateDAO<T>
implements IGenericDAO<T> {
//
}
Service class
Shows how to use autowire the generic dao in a service class and pass the model class a parameter. Also, do note that this implementation uses #Transactional annotation for spring transaction management.
#Service
public class TestService implements ITestService {
private IGenericDAO<TestModel> dao;
#Autowired
public void setDao(IGenericDAO<TestModel> daoToSet) {
dao = daoToSet;
dao.setClazz(TestModel.class);
}
#Override
#Transactional
public List<TestModel> findAll() {
return dao.findAll();
}
}
App Config
Shows how to set up spring for automatic transaction management using #EnableTransactionManagement
#Configuration
#ComponentScan("com.base-package")
#EnableTransactionManagement
public class AppConfig {
// add hibernate configuration
// add beans
}
In the applicationContext file I have added the package to map it.
The call arrives, but the variable is still null and does not pass to the server. In other classes, the same is working correctly.
Thanks in advance!
#ManagedBean(name="registerUser")
#SessionScoped
public class RegisterUser{
#ManagedProperty("#{userService}")
private DAOUser userService;
private User user = new User();
public DAOUser getUserService() {
return userService;
}
public void setUserService(DAOUser userService) {
this.userService = userService;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String register() {
// Calling Business Service
String passwordEncripada = PasswordControl.encriptString(user.getPassword());
user.setPassword(passwordEncripada);
userService.register(user);
// Add message
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Registro realizado"));
return "";
}
and DAOUser class:
#Component
public class DAOUser implements Serializable {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Transactional
public void register(User user){
// Acquire session
Session session = sessionFactory.getCurrentSession();
// Save employee, saving behavior get done in a transactional manner
session.save(user);
}
}
EDIT: The setter is called, but the object it sends is null
I think the problem was in the normalization of the DAOUser class name. I have gone to use #Repository ("userService") instead of #Component and it is already working.
#Repository("userService")
public class DAOUser implements Serializable {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Transactional
public void register(User user){
// Acquire session
Session session = sessionFactory.getCurrentSession();
// Save employee, saving behavior get done in a transactional manner
session.save(user);
}
}
In my Spring project I want to update mysql table field according to the url :
I have url below:
localhost:9191/access/name/article?key=xyz
I want to fetch the article from url and then update the status and article field of the corrsponding mysql table
In my database I have the table name "user".
user(stu_id,name,email,article,status)
mysql query is:
UPDATE user
SET article='null', status=true
WHERE article='xyz'; here xyz=user.getArticle()
To achieve this I have done the below
User.java is:
public User(String article, String status) {
super();
this.article = article;
this.status = status;
}
UserDao.java
public interface UserDao {
public void updateUser(User user);
}
UserDaoImpl.java is:
#Transactional
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public void updateUser(User user) {
String hql = "update user set article = null,status=true"
+"where article=:key1";
sessionFactory.getCurrentSession().createQuery(hql)
.setParameter("key1", user.getArticle());
}
}
UserService.java is:
public interface UserService {
User updateUser(String article, String status);
}
UserServiceImpl.java is:
#Service("userService")
#Transactional(propagation = Propagation.SUPPORTS)
public class UserServiceImpl implements UserService {
public User updateUser(String article, String status) {
User user = new User(article,status);
userDao.updateUser(user);
return user;
return user;
}
UserController.java is:
//localhost:9191/access/name/article?key=xyz
#RequestMapping(value="/access/name/id", method=RequestMethod.GET)
public #ResponseBody String byParameter( User user, HttpServletRequest request) {
boolean ps=true;
String foo= request.getParameter("key");
userService.updateUserinfo(foo, ps);
return "signupLogin";
}
but it is showing error:
ERROR [] (ErrorCounter.java:56) - line 1:51: unexpected token: key
ERROR [] (ErrorCounter.java:56) - line 1:58: unexpected token: =
java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1760)
at com.student.dao.UserDaoImpl.updateUser(UserDaoImpl.java:40)
at com.student.service.UserServiceImpl.updateUserinfo(UserServiceImpl.java:66)
where is the problem?What am I doing wrong??
Make following correction into sql query use User in place of user into query.
String hql = "update User set article = null, status = true where article = :key1";
if you don't want to change this method then you can use createSqlQuery method in place of createQuery method .
this solution may be help.
at com.student.dao.UserDaoImpl.updateUser(UserDaoImpl.java:40)
you were executing the wrong query.you should do like below code:
#Transactional
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public void updateUser(User user) {
String hql = "update user set article = null,status=true"
+"where article=:key1";
sessionFactory.getCurrentSession().createSQLQuery(hql)
.setParameter("key1", user.getArticle());
}
}
the syntax is like:
where user(this is the database table ) and article,status are the fields
I have a question as to how this service and its DAO object are performing persistence transactions.
The service is performing transactions on the database - but it is not using a DAOImpl object - it is instead using an object which is an instance of the interface - and naturally has no implementation of any method signatures. This, in my mind, should not be able to perform any meaningful actions. Am I overlooking something here?
Full link to code
http://www.byteslounge.com/tutorials/spring-with-hibernate-persistence-and-transactions-example
#Service
public class UserManagerImpl implements UserManager {
#Autowired
private UserDAO userDAO;
#Override
#Transactional
public void insertUser(User user) {
userDAO.insertUser(user);
}
#Override
#Transactional
public User getUserById(int userId) {
return userDAO.getUserById(userId);
}
#Override
#Transactional
public User getUser(String username) {
return userDAO.getUser(username);
}
#Override
#Transactional
public List<User> getUsers() {
return userDAO.getUsers();
}
}
public interface UserDAO {
void insertUser(User user);
User getUserById(int userId);
User getUser(String username);
List<User> getUsers();
}
#Service
public class UserDAOImpl implements UserDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void insertUser(User user) {
sessionFactory.getCurrentSession().save(user);
}
#Override
public User getUserById(int userId) {
return (User) sessionFactory.
getCurrentSession().
get(User.class, userId);
}
#Override
public User getUser(String username) {
Query query = sessionFactory.
getCurrentSession().
createQuery("from User where username = :username");
query.setParameter("username", username);
return (User) query.list().get(0);
}
#Override
#SuppressWarnings("unchecked")
public List<User> getUsers() {
Criteria criteria = sessionFactory.
getCurrentSession().
createCriteria(User.class);
return criteria.list();
}
}
first of all , instance of an interface can not be created , reference variable can be created for interfaces. Nevertheless ,as i followed the link and found that you are learning Spring with Hibernate. Spring provide you a facility called Dependency Injection which is why there is #Autowire annotation in your UserManagerImpl class which means you have injected a dependency UserDAO in UserManagerImpl class , so on rum time ,spring will provide the instance of the class which implements UserDAO interface .What you are overlooking is thorough study of Spring concepts.by the way all the best .
I created a spring application where i decided to add a BaseDAO to eliminate redundant create,
update,delete,findByid,and findAll methods for every dao. So i created a baseDao and every dao should extend this BaseDAO.
BaseDaoImpl
public class BaseDAOImpl implements BaseDAO{
SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
#Override
public void create(ModelBase modelBase) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(modelBase);
}
#Override
public void update(ModelBase modelBase) {
Session session = this.sessionFactory.getCurrentSession();
session.update(modelBase);
}
#Override
public Collection findAll(Class aClass) {
Session session = this.sessionFactory.getCurrentSession();
Collection modelCols = session.createQuery("from "+aClass.getSimpleName()).list();
return modelCols;
}
#Override
public ModelBase findById(Class aClass, Integer id) {
Session session = this.sessionFactory.getCurrentSession();
ModelBase modelBase = (ModelBase) session.load(aClass, new Integer(id));
return modelBase;
}
}
Then i extends this Dao to each DAO
EmployeeDAOImp
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
}
I created a BaseService like this. But when i try to access BaseDAO methods from EmployeeDAO it returns null pointer exception.
Why this happen. I dont want to use genericDAO from google. Because we should create DAOs
for each model. I want to eliminate this. So I follow this method.
Have you though about Spring Data project & Spring Data JPA in particular?
This would save you lots of time, since you would no longer need to write your DAO / Repositories from scratch, all you need to do is enable Spring Data JPA, and add needed interfaces. It should save you tons of time.
http://projects.spring.io/spring-data-jpa/
http://spring.io/guides/gs/accessing-data-jpa/ - Sample project
Your are overriding setSessionFactory from base class for no reason, its already available with extending class EmployeeDAOImpl , either remove it or try below:
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{
//this reference should be from base class,
// the extending class ref is hiding base ref.
// private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
super.setSessionFactory(sf);
}
}
Something like the following should work (note the use of constructor rather than setter injection). In the BaseDAO:
public class BaseDAOImpl implements BaseDAO {
private final SessionFactory sessionFactory;
public BaseDAOImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Then in the Employee DAO:
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO {
#Inject
public EmployeeDAOImpl (SessionFactory sessionFactory) {
super(sessionFactory);
}
}
You can create generic dao.
#Repository("genericDao")
public class GenericDaoImpl<T,PK extends Serializable> implements GenericDao<T, PK> {
protected Class<T> entityClass;
public T create(T t) {
this.entityManager.persist(t);
return t;
}
public T read(PK id,Class<T> c) {
return (T)this.entityManager.find(c, id);
}
public T update(T t) {
return this.entityManager.merge(t);
}
public void delete(T t) {
t = this.entityManager.merge(t);
this.entityManager.remove(t);
}
public List<T> getAll(Class<T> c){
return this.entityManager.createQuery("SELECT o FROM "+ c.getName() +" o").getResultList();
}
}
UPDATED
You can use as following, TimeRange is a pojo class in the following example. If you do not want a service layer. You can use timeRangeDao in controller.
#Service("timeRangeService")
public class TimeRangeServiceImpl implements TimeRangeService{
#Autowired
GenericDao<TimeRange,Long> timeRangeDao;
public List<TimeRange> getAllTimeRanges(){
return timeRangeDao.getAll(TimeRange.class);
}
#Transactional
public void createTimeRange(TimeRange c) {
timeRangeDao.create(c);
}
#Transactional
public void update(TimeRange p) {
timeRangeDao.update(p);
}
#Transactional
public TimeRange getTimeRange(long id) {
return timeRangeDao.read(id, TimeRange.class);
}
#Transactional
public void delete(long id) {
TimeRange timeRange = new TimeRange();
timeRange.setId(id);
timeRangeDao.delete(timeRange);
}
}