package com.idleworx.mybatisdao;
import java.util.ArrayList;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class contains all the basic CRUD related methods which are inherited by all objects.
* Children daos should generally not overwrite these method but add extra ones as needed.
*/
public abstract class MyBatisDAO<T, PK> implements IParentDAO<T, PK>{
private static Logger log = LoggerFactory.getLogger(MyBatisDAO.class);
private static final String NAMESPACE = "mappers";
private SqlSessionFactory sf; //reference to mybatis session factory
private Class<T> type;
/**
* Define prefixes for easier naming convetions between XML mapper files and the DAO class
**/
public static final String PREFIX_SELECT_QUERY = "get"; //prefix of select queries in mapper files (eg. getAddressType)
public static final String PREFIX_INSERT_QUERY = "create"; //prefix of create queries in mapper files (eg. createAddressType)
public static final String PREFIX_UPDATE_QUERY = "update"; //prefix of update queries in mapper files (eg. updateAddressType)
public static final String PREFIX_DELETE_QUERY = "delete"; //prefix of delete queries in mapper files (eg. deleteAddressType)
/** Default Constructor */
public MyBatisDAO(Class<T> type,SqlSessionFactory sf) {
this.type = type;
this.sf = sf;
if(sf==null)
log.error("Error: Could not instantiate MyBatisDAO. Loading myBatis sessionFactory failed.");
}
/** Use this method to get a session factory for using in any methods impelmented in child dao classes */
protected SqlSessionFactory getSessionFactory() {
return sf;
}
/**
* Default get by id method.
* </br></br>
* Almost all objects in the db will
* need this (except mapping tables for multiple joins, which you
* probably shouldn't even have as objects in your model, since proper
* MyBatis mappings can take care of that).
* </br></br>
* Example:
* </br>
* If your DAO object is called CarInfo.java,
* the corresponding mapper query id should be: <select id="getCarInfo" ...
*/
public T get(PK id) throws PersistenceException {
SqlSession session = sf.openSession();
T obj = null;
try
{
String query = NAMESPACE+"."+PREFIX_SELECT_QUERY+this.type.getSimpleName(); //If the object's calls name is AddressType.java, this matches the mapper query id: "namespace.getAddressType"
obj = (T)session.selectOne(query,id);
}
finally
{
session.close();
}
return obj;
}
/**
* Method returns all rows for this object.
* </br></br>
* Example:
* </br>
* If your DAO object is called CarInfo.java,
* the corresponding mapper query id should be: <select id="getAllCarInfo" ...
* </br></br>
* SQL Executed: select * from [tablename]
* </br></br>
* Notes:
* </br>
* Consider overdiding this method in order to handle large numbers of objects
* with multiple references.
* LAZY LOADING should be enabled in this case, otherwise you might run out of memory (eg. get all UserAccounts if the table has 1,000,000 rows)
* look into the aggresiveLazyLoading property
* */
public ArrayList<T> getAll() throws PersistenceException {
SqlSession session = sf.openSession();
ArrayList<T> list = null;
try
{
String query = NAMESPACE+"."+PREFIX_SELECT_QUERY+"All"+this.type.getSimpleName();
list = (ArrayList<T>)session.selectList(query);
}
finally
{
session.close();
}
return list;
}
/**
* Method returns first object which matches the given name (exact match).
* </br></br>
* It's up to you to decide what constitutes an object's name. Typically you would have a
* NAME column in the table, but not all objects have this. Generally this method should be overriden (if you need it at all)
* in the child dao class.
* </br></br>
* Example:
* </br>
* If your DAO object is called CarInfo.java,
* the corresponding mapper query id should be: <select id="getCarInfoByName" ...
* </br></br>
* SQL Executed (example): select * from [tablename] where NAME = ?
*
*/
public T getByName(String name) throws PersistenceException {
SqlSession session = sf.openSession();
T obj = null;
try
{
String query = NAMESPACE+"."+PREFIX_SELECT_QUERY+this.type.getSimpleName()+"ByName";
obj = (T)session.selectOne(query,name);
}
finally
{
session.close();
}
return obj;
}
/**
* Method inserts the object into the table.
* </br></br>
* You will usually override this method, especially if you're inserting associated objects.
* </br>
* Example:
* </br>
* If your DAO object is called CarInfo.java,
* the corresponding mapper query id should be: <insert id="createCarInfo" ...
* </br></br>
* SQL Executed (example): insert into [tablename] (fieldname1,fieldname2,...) values(value1,value2...) ...
*
*/
public int create(T o) throws PersistenceException{
SqlSession session = sf.openSession();
Integer status = null;
try
{
String query = NAMESPACE+"."+PREFIX_INSERT_QUERY+o.getClass().getSimpleName();
status = (Integer)session.insert(query,o);
session.commit();
}
finally
{
session.close();
}
return status;
}
/**
* Method updates the object by id.
* </br></br>
* You will usually override this method. But it can be used for simple objects.
* </br>
* Example:
* </br>
* If your DAO object is called CarInfo.java,
* the corresponding mapper query id should be: <update id="updateCarInfo" ...
* </br></br>
* SQL Executed (example): update [tablename] set fieldname1 = value1 where id = #{id}
*
*/
public int update(T o)throws PersistenceException {
SqlSession session = sf.openSession();
Integer status = null;
try
{
String query = NAMESPACE+"."+PREFIX_UPDATE_QUERY+o.getClass().getSimpleName();
status = session.update(query,o);
session.commit();
}
finally
{
session.close();
}
return status;
}
/**
* Method deletes the object by id.
* </br></br>
* Example:
* </br>
* If your DAO object is called CarInfo.java,
* the corresponding mapper query id should be: <delete id="deleteCarInfo" ...
* </br></br>
* SQL Executed (example): update [tablename] set fieldname1 = value1 where id = #{id}
*
*/
public int delete(PK id) throws PersistenceException{
SqlSession session = sf.openSession();
Integer status = null;
try
{
String query = NAMESPACE+"."+PREFIX_DELETE_QUERY+this.type.getSimpleName();
status = session.delete(query,id);
session.commit();
}
finally
{
session.close();
}
return status;
}
}