天天看点

Hibernate学习手记(3)--规范的DAO

建立实用且规范的DAO 操作类

J2EE中倡导的应该是面向接口,而不是面向类来编程,因为只有面向接口,才能真正做到层与层之间的解耦。面向接口编程最重要的价值在于隐藏实现,将抽象的实现细节封装起来不对外开放。

在大多数情况下,还需要对抽象类提取必要的接口,简单来做就是,把抽象DAO 类中的方法,全部抽取出来形成一个单独的接口。假如所有 DAO 的操作方法都一样,这样做没问题。但是实际上各个 DAO 类之间,尽管有大量相同的方法,但也总是存在一些不一致的方法,这样一来,问题就来了。我们总不能把接口做的很大吧 ....

接口隔离原则(ISP ):使用多个专门的接口比使用单一的总接口好!

实现这个原则的通常的方式有两种:

(1 )使用委托分离接口

(2 )使用多重继承分离接口

具体到抽象DAO 类,我们应该为所有具体的 DAO 类的共性方法抽取到抽象 DAO 类中,并将这些方法抽象为接口,之后再为每个具体的 DAO 类定义接口,在此接口中定义不再抽象 DAO 类中的方法,最后具体的 DAO 类应该继承抽象 DAO 类,同时实现本 DAO 类所对应的接口。通过这样的方式,就可以做到接口的隔离和防止大接口形成的污染了。

具体步骤如下:

1、 先建立一个HibernateSessionFactory 类来实现 Session 的创建与回收。

主要代码见下:

........

public class HibernateSessionFactory {

    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";

private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

    private  static Configuration configuration = new Configuration();    

    private static org.hibernate.SessionFactory sessionFactory;

    private static String configFile = CONFIG_FILE_LOCATION;

static {

     try {

configuration.configure(configFile);

sessionFactory = configuration.buildSessionFactory();

} catch (Exception e) {

System.err

.println("%%%% Error Creating SessionFactory %%%%");

e.printStackTrace();

}

    }

     public static Session getSession() throws HibernateException  {

        Session session = (Session) threadLocal.get();

if (session == null || !session.isOpen()) {

if (sessionFactory == null) {

rebuildSessionFactory();

}

session = (sessionFactory != null) ? sessionFactory.openSession(): null;

threadLocal.set(session);

}

        return session;

    }

     public static void closeSession() throws HibernateException  {

        Session session = (Session) threadLocal.get();

        threadLocal.set(null);

        if (session != null) {

            session.close();

        }

}

............

}

2、 定义一个IBaseHibernateDAO 接口,用来定义每个实体 DAO 类的公共方法,如 getSession() , save() , delete() 等,然后再建一个 BaseHibernate 类来实现该接口。

public  interface  IBaseHibernateDAO {

public  Session getSession();

public   void  save(Object transientInstance);

public   void  delete(Object transientInstance); 

}

public   class  BaseHibernateDAO  implements  IBaseHibernateDAO {

public  Session getSession() {

return  HibernateSessionFactory. getSession ();

}

public   void  delete(Object transientInstance) throws  RuntimeException {

getSession().delete(transientInstance);

}

public   void  save(Object transientInstance) throws  RuntimeException {

getSession().save(transientInstance);

}

}

3、 设计每个实体DAO 类的时候,先为其定义一个接口,定义其 特有的操作方法 ,如:

public   interface  IClientDAO  extends  IBaseHibernateDAO  {

public  Client findById(java.lang.String id);

public   List  findByExample(Client instance);

public   List  findByProperty(String propertyName, Object value) ;

public   List  findByCEmail(Object CEmail) ;

public   List  findByCPhone(Object CPhone) ;

public   List  findByCName(Object CName);

public   List  findByCSex(Object CSex) ;

public   List  findAll();

public  Client merge(Client detachedInstance);

public   void  attachDirty(Client instance);

public   void  attachClean(Client instance);

}

public class ClientDAO extends BaseHibernateDAO implements IClientDAO{

private static final Log log = LogFactory.getLog(ClientDAO.class);

// property constants

public static final String _CEMAIL = "CEmail";

public static final String _CPHONE = "CPhone";

public static final String _CNAME = "CName";

public static final String _CSEX = "CSex";

public void save(Client transientInstance) {

log.debug("saving Client instance");

try {

super.save(transientInstance);

log.debug("save successful");

} catch (RuntimeException re) {

log.error("save failed", re);

throw re;

}

}

public void delete(Client persistentInstance) {

log.debug("deleting Client instance");

try {

super.delete(persistentInstance);

log.debug("delete successful");

} catch (RuntimeException re) {

log.error("delete failed", re);

throw re;

}

}

public Client findById(java.lang.String id) {

log.debug("getting Client instance with id: " + id);

try {

Client instance = (Client) getSession().get("com.DB.Entity.Client", id);

return instance;

} catch (RuntimeException re) {

log.error("get failed", re);

throw re;

}

}

public List findByExample(Client instance) {

log.debug("finding Client instance by example");

try {

List results = getSession().createCriteria("com.DB.Entity.Client").add(

Example.create(instance)).list();

log.debug("find by example successful, result size: "

+ results.size());

return results;

} catch (RuntimeException re) {

log.error("find by example failed", re);

throw re;

}

}

public List findByProperty(String propertyName, Object value) {

log.debug("finding Client instance with property: " + propertyName

+ ", value: " + value);

try {

String queryString = "from Client as model where model."

+ propertyName + "= ?";

Query queryObject = getSession().createQuery(queryString);

queryObject.setParameter(0, value);

return queryObject.list();

} catch (RuntimeException re) {

log.error("find by property name failed", re);

throw re;

}

}

public List findByCEmail(Object CEmail) {

return findByProperty(_CEMAIL, CEmail);

}

public List findByCPhone(Object CPhone) {

return findByProperty(_CPHONE, CPhone);

}

public List findByCName(Object CName) {

return findByProperty(_CNAME, CName);

}

public List findByCSex(Object CSex) {

return findByProperty(_CSEX, CSex);

}

public List findAll() {

log.debug("finding all Client instances");

try {

String queryString = "from Client";

Query queryObject = getSession().createQuery(queryString);

return queryObject.list();

} catch (RuntimeException re) {

log.error("find all failed", re);

throw re;

}

}

}

4、建立一个工厂类来对DAO进行统一的管理,该工厂类采用xml文件配置方式来反射生成DAO实例

public   class  DAOFactory {

//建立一个 DAO 实例的缓冲池

private  Map<String,Object>  daoMap  =  new  HashMap<String,Object>();

//建立 DAO 工厂实例

private   static  DAOFactory  df ;

//初始化 DAO 工厂

public  DAOFactory() throws  Exception{

Document doc =  new  SAXReader().read( new  File( " . /DAOContext.xml" ));

Element root = doc.getRootElement(); //由 document 获得 xml 文件的根元素

List  list = root.elements(); //由根元素得到所有元素

for ( Iterator  it = list.iterator();it.hasNext();){

Element em = (Element) it.next();

String id = em.attributeValue( "id" );

String dao = em.attributeValue( "class" ); //得到 class 表示字符串

Class  daoClass = Class. forName (dao); //把该字符串变成一个具体的类

Object odj = daoClass.newInstance(); //生成该类的对象

daoMap .put(id, odj); //把该对象放到 DAO 缓冲池里

}

}

//提供一个普通的入口方法,用以返回一个 DAOFactory 的实例

public   static  DAOFactory instance(String path) throws  Exception{

if ( df == null ){

df = new  DAOFactory();

}

return   df ;

}

//获得具体的 DAO 实例

public  Object getDAO(String id){

return   daoMap .get(id);

}

protected  Session getCurrentSession(){

return  com.DAO.HibernateSessionFactory. getSession ();

}

}

6、 Junit测试实例:

public   class  TestDAOFactory {

@Before

public   void  setUp()  throws  Exception {

}

@After

public   void  tearDown()  throws  Exception {

}

@Test

public   void  DAOFactoryTest(){

DAOFactory df;

try  {

df =  new  DAOFactory();

IClientDAO clientDAO = (IClientDAO) df.getDAO( "ClientDAO" );

HibernateSessionFactory. getSession ().beginTransaction();

Client client =  new  Client();

client.setCVip( "0001" );

client.setCName( "zhiwei" );

client.setCSex( "m" );

client.setCPhone( "110" );

clientDAO.save(client);

HibernateSessionFactory. getSession ().getTransaction().commit();

System. out .println(clientDAO.findByCName( "zhiwei" ).toString());

}  catch  (Exception e) {

e.printStackTrace();

}

}

}