J2EE開發架構搭建(6) - 使用hibernate4完成基本Dao的封裝

來源:互聯網
上載者:User

標籤:hibernate4   基本dao操作   spring   maven   架構整合   

現在orm架構有很多,比如說guzz,hibernate,mybaits....,在封裝一個架構的時候我們可以選擇一種,也可以選擇多種實現,供以後使用選擇,這裡我只實現了hibernate,目錄結構圖如下:

1. 首先查詢BaseRepository這個介面,該介面泛型 :T 表示實體類型;ID表示主鍵類型;雖然在架構裡面已經提供了查詢的結構Searchable,但是Searchable也不能做到無限強大,比如一個多變關聯查詢,巢狀查詢是沒有辦法完成的,所有只能自己編寫sql語句,但是hibernate編寫sql語句都只能寫在java代碼裡面,用過mybaits的朋友就知道sql語句可以配置在xml裡面 ,這裡我們就可以簡單的仿照mybaits來完成,在這個介面中就提供了調用xml中的sql語句的方法,具體怎麼實現後面再說明:

package com.hqhop.framework.common.orm;///import ...../** * <p> * 抽象DAO層基類 提供一些簡便方法<br/> * <p/> * <span style="color:#ff0000;">泛型 :T 表示實體類型;ID表示主鍵類型</span> * <p> * Version: 1.0 *  * @author silentwu */public interface BaseRepository<T extends AbstractEntity<ID>, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {/** * 根據主鍵刪除 *  * @param ids */public void delete(ID... ids);/** * 根據條件查詢所有 條件 + 分頁 + 排序 *  * @param searchable * @return */public Page<T> findAll(Searchable searchable);/** * 根據條件統計所有記錄數 *  * @param searchable * @return */public long count(Searchable searchable);public void update(T entity);/** * 自訂sql更新 *  * @param sqlKey * @param params */public void update(String sqlKey, Object... params);/** * 自訂sql查詢 *  * @param sqlKey * @param params * @return */public List<T> findAll(String sqlKey, Object... params);public Page<T> findPage(Pageable pageable, String sqlKey, Object... params);/** * 自訂sql刪除 *  * @param sqlKey * @param params */public void delete(String sqlKey, Object... params);}

該介面繼承了spring的PagingAndSortingRepository介面, 然而PagingAndSortingRepository又繼承了CrudRepository介面,所以BaseRepository就具有了基本的增刪改查以及自己定義的一些方法:

@NoRepositoryBeanpublic interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {Iterable<T> findAll(Sort sort);Page<T> findAll(Pageable pageable);}
@NoRepositoryBeanpublic interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {<S extends T> S save(S entity);<S extends T> Iterable<S> save(Iterable<S> entities);T findOne(ID id);boolean exists(ID id);Iterable<T> findAll();Iterable<T> findAll(Iterable<ID> ids);long count();void delete(ID id);void delete(T entity);void delete(Iterable<? extends T> entities);void deleteAll();}
2. 接下來查看BaseRepository的實作類別BaseRepositoryImpl,由於要使用hibernate操作資料庫,所以要提供session,在hibernate4中已經建議直接使用session操作資料庫,建議不要在使用hibernateTemplate;要使用sessionFactory.getCurrentSession()來擷取當前的線程中的session就必須開啟事物,所以在spring-config.xml中加入下代碼:

<!-- 開啟註解事務 只對當前設定檔有效 --><tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /><!-- 配置Hibernate交易管理員 --><bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory" /></bean>
在BaseRepositoryImpl就可以使用如下代碼了:

@Autowiredprivate SessionFactory sessionFactory;public Session getSession() {// 事務必須是開啟的(Required),否則擷取不到return sessionFactory.getCurrentSession();}
3. 在BaseRepositoryImpl中還必須要有一個Class 屬性,指定運行時刻BaseRepositoryImpl操作的實體類,因為在hibernate中做了sql查詢或者是hql查詢,查詢的結果通過反射轉化為實體類返回到service。那麼又怎麼給這個Class對象賦值呢?在這裡我們需要自己定義一個註解Repository,在這個註解中就記錄了BaseRepositoryImpl要操作的實體類:

/** *  * @author silentwu * */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@org.springframework.stereotype.Repositorypublic @interface Repository {/** * Repository在spring容器中的執行個體名稱 */String value() default "";/** * Repository處理的實體類 *  * @return */Class<?> entity();}
接下來我們就可以直接在BaseRepositoryImpl中擷取這個註解來得到Class,在BaseRepositoryImpl中添加如下代碼:

private Class<T> clazz;@PostConstruct@SuppressWarnings("unchecked")public void init() throws Exception {<span style="color:#ff0000;">Repository repository = this.getClass().getAnnotation(Repository.class);</span>if (Utils.isNotEmpty(repository)) {if (Utils.isNotEmpty(repository.entity())) {<span style="color:#ff0000;">this.clazz = (Class<T>) repository.entity();</span>this.countAllQL = String.format(COUNT_QUERY_STRING, clazz.getName());this.findAllQL = String.format(FIND_QUERY_STRING, clazz.getName());} else {throw new Exception(Repository.class + "註解的entity不可為空!");}} else {throw new Exception(this.getClass() + " 必須要使用" + Repository.class + "註解!");}}
在init()方法上面添加了@PostConstruct註解,表示在類被spring容器執行個體化後要執行的方法;也可以實現spring的InitializingBean介面來達到同樣的效果(但是spring已經不推薦使用這種方式)

4. 在前面的章節中,我們提供了邏輯刪除的介面LogicDeleteable,具體實現邏輯的刪除就是在BaseRepositoryImpl中,在BaseRepositoryImpl中提供了多個刪除方法,但是主要的刪除操作只有一個delete(T entity),其他的刪除都是調用的這個:

/** * 檢查是否實現了邏輯刪除介面 *  * @return */private boolean checkLogicDeleteable() {Class[] inters = this.clazz.getInterfaces();boolean flag = false;for (int i = 0; i < inters.length; i++) {if ("LogicDeleteable".equals(inters[i].getSimpleName())) {flag = true;break;}}return flag;}@Overridepublic void delete(T entity) {if (Utils.isNotEmpty(entity)) {if (entity instanceof LogicDeleteable) {((LogicDeleteable) entity).markDeleted();update(entity);} else {this.getSession().delete(entity);}}}
在刪除對象的時候首先判斷是否實現了LogicDeleteable介面,若為true  ==> 調用markDeleted(); 否則真實刪除。

5. BaseRepository,BaseRepositoryImpl的使用方式,操作User實體類:

介面UserDao

public interface UserDao extends BaseRepository<User, String> {}
實作類別UserDaoImpl,使用@Repository註解,指定操作的實體類

@Repository(entity = User.class)public class UserDaoImpl extends BaseRepoitoryImpl<User, String> implements UserDao {}













J2EE開發架構搭建(6) - 使用hibernate4完成基本Dao的封裝

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.