Spring3整合Hibernate4-我們到底能走多遠系列(30)


我們到底能走多遠系列(30)

扯淡:

  30篇啦!從2012-08-15開始的系列,東平西湊將近一年的時間也就這么幾篇。目標的100篇,按這個速度也要再搞兩年呢。

  發博客果然不是件容易的事,怪不得更多的人願意玩微博,125個字,寫一個字也可以發了。

  向那些依然堅持穩定碼博客的朋友致敬!

主題:

  用spring整合hibernate也算是java web開發的入門必學的東西了,多年下來沒怎么用過hibernate。

  所以記錄下基礎的整合知識,以及如何構建一些共通的代碼,減少dao層的工作量。

  項目使用maven構建,關於maven的構建知識可以參考:摸我

  整合只使用了一個配置文件,hibernate方面使用注解方式映射數據庫表。

 

data-source.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    "
    default-autowire="byName">
    <context:component-scan base-package="com.sz.sh.dal.dao.hibernate,com.sz.sh.dal.dao.dateobject">
    </context:component-scan>
    <!-- 使用常規的BasicDataSource 來配置DataSource-->
    <bean id="shDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="${sh.jdbc.url}" />
        <property name="username" value="${sh.jdbc.username}" />
        <property name="password" value="${sh.jdbc.password}" />
        <property name="initialSize" value="1" />
        <property name="maxIdle" value="30" />
        <property name="maxWait" value="10000" />
        <property name="minIdle" value="1" />
        <property name="removeAbandoned" value="true" />
        <property name="removeAbandonedTimeout" value="180" />
        <!-- validate connection 檢測配置 -->
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="validationQuery">
            <value>SELECT @@SQL_MODE</value>
        </property>
        <property name="numTestsPerEvictionRun">
            <value>30</value>
        </property>
        <property name="timeBetweenEvictionRunsMillis">
            <value>60000</value>
        </property>
        <property name="minEvictableIdleTimeMillis">
            <value>1800000</value>
        </property>
    </bean>
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="shDataSource" />
    </bean>

    <bean id="transactionTemplate"
        class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager" />
    </bean>
    <bean id="shSessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="shDataSource" />
        <property name="packagesToScan">
            <list>
                <value>com.sz.sh.dal.dao.dateobject</value>
            </list>
        </property>
        <!--  如果用xml來描述hibernate的bean,就需要以下的配置
        <property name="mappingResources"> 
            <list> 
                <value>cn/sh/model/user.hbm.xml</value> 
               </list> 
        </property>
        -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.default_schema">wxassistant</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.query.substitutions">false</prop>
                <prop key="hibernate.default_batch_fetch_size">20</prop>
                <prop key="hibernate.max_fetch_depth">2</prop>
                <prop key="hibernate.generate_statistics">true</prop>
            </props>
        </property>
    </bean>
    <aop:aspectj-autoproxy expose-proxy="true" /><!-- 開啟注解事務 只對當前配置文件有效 -->
    <tx:annotation-driven transaction-manager="txManager" />
    <bean id="txManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="shSessionFactory" />
    </bean>
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="merge*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="put*" propagation="REQUIRED" />
            <tx:method name="use*" propagation="REQUIRED" />
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="count*" propagation="REQUIRED" read-only="true" />
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="list*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*"  propagation="REQUIRED" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <aop:config expose-proxy="true"><!-- 只對業務邏輯層實施事務 -->
        <aop:pointcut id="txPointcut"
            expression="execution(* com.sz.sh.dal.dao.hibernate.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
    </aop:config>
    <!--hibernate4必須配置為開啟事務 否則 getCurrentSession()獲取不到  -->
    <aop:config expose-proxy="true">
        <aop:pointcut id="basePointcut"
            expression="execution(* com.sz.sh.dal.common.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="basePointcut" />
    </aop:config>
</beans>
View Code

項目目錄結構:

基礎DAO:

定義最基本的方法。

public interface BaseDAO<M extends java.io.Serializable, PK extends java.io.Serializable> {

    public PK save(M model);
    
    public void saveOrUpdate(M model);
    
    public void update(M model);
    
    public List<M> findByExample(M model);
    
    public List<M> findByCriterion(Criterion criterion, Order order, Integer offset, Integer length);
    
    public List<M> findByProperty(Map<String, Object> param, int offset, int length);
    
    public void merge(M model);
    
    public void delete(PK id);
    
    public boolean exists(PK id);
    
    public M get(PK id);
    
    public List<M> getALL();
    
    public Long countALL();
}

基礎DAO實現:核心的實現類

本抽象類中,實現了一些安主鍵查詢,分頁查詢,添刪改,等一些基本的操作。

而且,基本涵蓋了一些常用的利用hibernate處理數據庫的不同方法。

/**
 * @0 getSession().createQuery HQL查詢
 * @1 getSession().createSQLQuery NATIVE sql 查詢 使用 NATIVE sql可能出現屬性類型
 * sess.createSQLQuery("SELECT * FROM CATS").addScalar("ID", Hibernate.LONG).addScalar("NAME")
 * sess.createSQLQuery("SELECT ID NAME, BIRTHDATE FROM CATS").addEntity(Cat.class
 * @2 getSession().createCriteria Criteria 查詢 @ *
 * @param <M>
 * @param <PK>
 */
@MappedSuperclass
public abstract class BaseDAOHib<M extends java.io.Serializable, PK extends java.io.Serializable> implements BaseDAO<M , PK>{

    protected static final Logger LOGGER = LoggerFactory.getLogger(BaseDAOHib.class);

    private Class<M>              entityClass;
    private String                HQL_LIST_ALL;
    private String                HQL_COUNT_ALL;
    private String                pkName = "Id";

    @SuppressWarnings("unchecked")
    public BaseDAOHib(){
        this.entityClass = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        // TODO @Entity name not null
        HQL_LIST_ALL = "from " + this.entityClass.getSimpleName() + " order by " + pkName + " desc";
        HQL_COUNT_ALL = " select count(*) from " + this.entityClass.getSimpleName();
    }

    @Autowired
    @Qualifier("shSessionFactory")
    private SessionFactory sessionFactory;

    public Session getSession() {
        // 事務必須是開啟的(Required),否則獲取不到
        return sessionFactory.getCurrentSession();
    }

    @SuppressWarnings("unchecked")
    public PK save(M model) {
        return (PK) getSession().save(model);
    }

    public void saveOrUpdate(M model) {
        getSession().saveOrUpdate(model);
    }

    public void update(M model) {
        getSession().update(model);

    }

    public List<M> findByExample(M model) {
        List<M> results = getSession().createCriteria(this.entityClass).add(Example.create(model)).list();
        return results;
    }

    public List<M> findByCriterion(Criterion criterion, Order order, Integer offset, Integer length) {
        Criteria criteria = getSession().createCriteria(this.entityClass);
        criteria.add(criterion);

        if (order != null) {
            criteria.addOrder(order);
        }
        if (offset != null) {
            criteria.setFirstResult(offset);
        }
        if (length != null) {
            criteria.setMaxResults(length);
        }
        return criteria.list();
    }

    public List<M> findByProperty(Map<String, Object> param, int offset, int length) {

        StringBuffer queryString = new StringBuffer("from " + this.entityClass.getSimpleName() + "  where ");
        List<Object> values = new ArrayList<Object>();
        boolean firstparam = true;
        for (Map.Entry<String, Object> entry : param.entrySet()) {
            values.add(entry.getValue());
            if (!firstparam) {
                queryString.append(" and ");
            }
            queryString.append(entry.getKey() + "= ? ");
            firstparam = false;
        }
        Query queryObject = getSession().createQuery(queryString.toString());

        for (int i = 0; i < values.size(); i++) {
            queryObject.setParameter(0, values.get(i));
        }

        return queryObject.list();

    }

    public void merge(M model) {
        getSession().merge(model);
    }

    public void delete(PK id) {
        getSession().delete(this.get(id));

    }

    public boolean exists(PK id) {
        return get(id) != null;
    }

    public M get(PK id) {
        return (M) getSession().get(this.entityClass, id);
    }

    public List<M> getALL() {
        return getSession().createQuery(HQL_LIST_ALL).list();
    }

    public Long countALL() {
        return (Long) getSession().createQuery(HQL_COUNT_ALL).uniqueResult();
    }

}

 

具體對應表的DAO:注意繼承BaseDAO 這樣默認接口繼承者實現基礎類的共通方法。

public interface CategoryDAO extends BaseDAO<CategoryDO,Long>{

    public List<CategoryDO> getAllCategory();
    
    public CategoryDO getCategoryById(Long id);
}

具體對應表的DAO接口繼承者: 繼承了基礎DAO的實現,這樣一來就不需要自己實現了。

如此就實現了,所有對應表的DAO都公用了一份基礎DAO實現。大大的減少了DAO層的開發時間,降低了DAO層的bug率。

@Repository("categoryDAO")
public class CategoryDAOHibernate extends BaseDAOHib<CategoryDO,Long> implements CategoryDAO{

    @Override
    public List<CategoryDO> getAllCategory() {
        return super.getALL();
    }

    @Override
    public CategoryDO getCategoryById(Long id) {
        return get(id);
    }
}

 

 

另外貼上pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>work</groupId>
  <artifactId>Spring_Hibernate</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Spring_Hibernate</name>
  <url>http://maven.apache.org</url>
    
    <profiles>
        <!-- 開發環境,默認激活 -->
        <profile>
            <id>dev</id>
            <properties>
                <env>dev</env>
                <maven.test.skip>true</maven.test.skip>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
    </profiles>
    
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring-version>3.1.1.RELEASE</spring-version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.7.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.10</version>
    </dependency>
    <!-- ================================================= -->
    <!-- Spring框架 -->
    <!-- ================================================= -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring-version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring-version}</version>
    </dependency>
    <!-- ================================================= -->
    <!-- Hibernate -->
    <!-- ================================================= -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.1.9.Final</version>
    </dependency>
    
    <!-- ================================================= -->
    <!-- 日志及相關依賴(用slf4j+logback代替jcl+log4j) -->
    <!-- ================================================= -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.6.1</version>
    </dependency>
    <!-- 將現有的jakarta commons logging的調用轉換成lsf4j的調用。 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.6.1</version>
    </dependency>
    <!-- Hack:確保commons-logging的jar包不被引入,否則將和jcl-over-slf4j沖突 -->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- slf4j的實現:logback,用來取代log4j。更快、更強! -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>0.9.24</version>
        <scope>runtime</scope>
    </dependency>
  </dependencies>
  <build>            

        <defaultGoal>install</defaultGoal>
        <filters>
            <filter>${user.dir}/env/filter-${env}.properties</filter>
        </filters>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>    
        </resources>    

    </build>
</project>
View Code

 

 

 

讓我們繼續前行

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不會成功。
共勉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM