1. 程式人生 > >【面試之持久化框架】hibernate、mybatis、jpa規範

【面試之持久化框架】hibernate、mybatis、jpa規範

1.hibernate 和 mybatis 的區別

    ·實現上的區別:mybatis只有一個核心jar包,另外和spring整合需要mybatis-spring的jar包,使用快取需要mybatis-ehcache的jar包,而hibernate需要一系列的jar包,這也側面反映了mybatis相對小巧,簡單,而hibernate相對來說比較強大,複雜;mybatis的配置主要包括一個用於對映各種類的xml檔案以及和實體類一一對應的對映檔案,hibernate包括hibernate.cfg.xml和實體類的配置檔案hibernate.hbm.xml。

    ·hibernate屬於全自動的ORM框架,著力點在於POJO和資料庫表之間的對映,完成對映即可自動生成和執行sql;而mybatis相對來說屬於半自動的ORM框架,著力點在於POJO和SQL之間的對映,自己編寫sql語句,然後通過配置檔案將所需的引數和返回的欄位對映到POJO。如果說hibernate屬於ORM Mapping,那麼mybatis相當於SQL Mapping.

    ·從上面的描述也可以看出,hibernate整合的專案比mybatis整合的專案更容易移植,因為hibernate使用的HQL語句與具體的資料庫無關,而mybatis編寫的sql語句都是和資料庫相關聯的,可移植性差。

    ·hibernate擁有自己的日誌統計slf4j,而mybatis自身不帶有日誌記錄。

    ·快取方面,都可以使用第三方的快取。hibernate有一級快取和二級快取之分,一級快取屬於session級別的快取,需要對session的生命週期進行管理,二級快取屬於sessionFactory級別的快取;mybatis雖然也有一級快取,但是和spring整合使用時每次都是重新開啟一個session進行操作,所以是無法使用,當然可以開啟二級快取,被所有sqlsessiong共享。

    ·mybatis需要手動寫sql語句,這既是好的一面也是不好的一面,與hibernate相比好的一面在於可以高度優化sql語句以提升系統性能;不好的一面在於工作量相對比較大;如果牽扯到資料庫的修改,則mybatis相對於hibernate的修改量更大

    ·學習成本上,hibernate相對來說,週期比較長。

第三方快取 ehcache配置:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="false" monitoring="autodetect"
         dynamicConfig="true">

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

    <!--Predefined caches.  Add your cache configuration settings here.
        If you do not have a configuration for your cache a WARNING will be issued when the
        CacheManager starts

        The following attributes are required for defaultCache:

        name              - Sets the name of the cache. This is used to identify the cache. It must be unique.
        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->

    <!-- Sample cache named sampleCache1
        This cache contains a maximum in memory of 10000 elements, and will expire
        an element if it is idle for more than 5 minutes and lives for more than
        10 minutes.

        If there are more than 10000 elements it will overflow to the
        disk cache, which in this configuration will go to wherever java.io.tmp is
        defined on your system. On a standard Linux system this will be /tmp"
        //秒-->
    <cache name="parameterCache"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="0"
        timeToLiveSeconds="300"
        overflowToDisk="false"
        diskPersistent="false"
        memoryStoreEvictionPolicy="LRU"
        />

    <!-- Sample cache named sampleCache2
        This cache contains 1000 elements. Elements will always be held in memory.
        They are not expired. -->
  <!--  <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->

    <!-- Place configuration for your caches following -->

</ehcache>
micro(比較全的配置)
    <defaultCache
            maxElementsInMemory="10000"
            maxElementsOnDisk="100000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />

    <cache
            name="com.raipeng.micro.core.module.common.entity.ConfigEntity"
            maxElementsInMemory="10000"
            maxElementsOnDisk="100000"
            timeToIdleSeconds="3600"
            timeToLiveSeconds="3600"
            eternal="true"
            overflowToDisk="true"
            diskSpoolBufferSizeMB="50"
            />


mybatis的一些配置

mybatisconfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.*.sales.entity"/>
    </typeAliases>
	<mappers>
 	  	<mapper resource="com/*/sales/front/repository/mybatis/sales.xml"/>
                <mapper resource="com/*/sales/front/repository/mybatis/saleOrder.xml"/>
                <mapper resource="com/*/sales/front/repository/mybatis/distributorAccount.xml"/>
                <mapper resource="com/*/sales/front/repository/mybatis/snsUser.xml"/>
                <mapper resource="com/*/sales/front/repository/mybatis/rechargeOrder.xml"/>
                <mapper resource="com/*/sales/front/repository/mybatis/poster.xml"/>
                <mapper resource="com/*/sales/front/repository/mybatis/withdrawRecord.xml"/>
                <mapper resource="com/*/sales/front/repository/mybatis/flowProduct.xml"/>
	</mappers>
</configuration>
其中一個pojo
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.*.sales.entity.DistributorAccount">
    <resultMap id="distributorAccountResultMap" type="distributorAccount">
        <id property="id" column="id"></id>
        <result property="operatorId" column="operator_id"></result>
        <result property="orderNo" column="orderno"></result>
        <result property="price" column="price"></result>
        <result property="mobile" column="mobile"></result>
        <result property="flowPackage" column="flow_package"></result>
        <result property="operatorType" column="operator_type"></result>
        <result property="status" column="status"></result>
        <result property="createdDate" column="created_date"></result>
        <result property="finishDate" column="finish_date"></result>
        <result property="lastModified" column="last_modified"></result>
        <result property="remark" column="remark"></result>
        <result property="sellerId" column="seller_id"></result>
        <result property="version" column="version"></result>
        <result property="refundOperatorId" column="refund_operator_id"></result>
    </resultMap>

    <select id="selectDistributorAccountList" parameterType="distributorAccountForm" resultMap="distributorAccountResultMap">
        select o.* from rp_app_account o
        <where>
              o.seller_id = #{operatorId}
            <if test="beginDateStr != null and beginDateStr != ''">
                AND DATE_FORMAT(o.last_modified,'%Y-%m-%d') >= str_to_date(#{beginDateStr},'%Y-%m-%d')
            </if>
            <!--%Y-%m-%d %H:%i:%s-->
            <if test="endDateStr != null and endDateStr != ''">
                <![CDATA[
                and DATE_FORMAT(o.last_modified,'%Y-%m-%d') <= str_to_date(#{endDateStr},'%Y-%m-%d')
                ]]>
            </if>
            <if test="operatorType != null and operatorType != ''">
                and o.operator_type = #{operatorType}
            </if>
        </where>
        order by o.last_modified desc
        limit #{offset},#{pageSize}
    </select>

    <insert id="saveDistributorAccount" >
        insert into rp_app_account (operator_id,orderno,price,mobile,flow_package,operator_type,status,created_date,finish_date,last_modified,remark,seller_id,version)
        values (#{operatorId},#{orderNo},#{price},#{mobile},#{flowPackage},#{operatorType},#{status},now(),#{finishDate},now(),#{remark},#{sellerId},#{version})
    </insert>

    <update id="updateStatusByOrderNo" >
        update rp_app_account set status = #{status} ,last_modified = now(),refund_operator_id = #{refundOperatorId} where orderno = #{orderNo}
    </update>
</mapper>
DaoImpl繼承該抽象類即可使用sqlsession

import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * @author 
 * 
 */
public abstract class AbstractMyBatisBaseRepository extends
		SqlSessionDaoSupport {
	@Autowired
	public final void init(SqlSessionTemplate sessionTemplate) {
		this.setSqlSessionTemplate(sessionTemplate);
	}
}

和spring整合的配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/aop   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
	http://www.springframework.org/schema/tx    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	
 	<context:property-placeholder location="classpath:sysconfig.properties" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close" p:driverClassName="${jdbc.mysql.driverClassName}"
		p:url="${jdbc.mysql.url}" p:username="${jdbc.mysql.username}"
		p:password="${jdbc.mysql.password}" p:maxActive="100000" p:maxIdle="10"
		p:testOnBorrow="true" p:validationQuery="select 1" >

		<description>開發環境本地庫配置</description>
	</bean>
	

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
		p:dataSource-ref="dataSource" p:configLocation="classpath:mybatisconfig.xml" />

	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory" />
	</bean>

	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
		p:dataSource-ref="dataSource" />
	
		
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="mod*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="find*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="load*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="query*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="export*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="cancle*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="logout*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="*" read-only="true" />
		</tx:attributes>
	</tx:advice>

	<!-- 通過AOP實現橫向切入 -->
	
	<aop:config>
		<aop:advisor pointcut="execution(* com.raipeng.sales.*.service.*.*(..))" advice-ref="txAdvice" />
	</aop:config>
</beans>
配置cache
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:cache="http://www.springframework.org/schema/cache"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
	<context:component-scan base-package="com.raipeng.sales" />
	<tx:annotation-driven />

<cache:annotation-driven cache-manager="cacheManager" />

	<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
		p:cacheManager-ref="ehcache" />

	<!-- Ehcache library setup -->
	<bean id="ehcache"
		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
		p:configLocation="classpath:ehcache.xml" /> 

</beans>
都匯入到spring配置檔案中,用import
jpa的配置檔案persistenceContext.xml,hibernate實現
<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:util="http://www.springframework.org/schema/util"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       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/util http://www.springframework.org/schema/util/spring-util-4.1.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
			http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <jpa:repositories base-package="com.raipeng.micro.core.module.**.dao" />

    <jpa:auditing/>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"
          p:jndiName="java:comp/env/jdbc/microDB"/>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory"/>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          p:dataSource-ref="dataSource"
          p:packagesToScan="com.raipeng.micro.core.module.**.entity"
          p:jpaVendorAdapter-ref="jpaVendorAdapter"
          p:jpaProperties-ref="jpaProperties"/>

    <util:properties id="jpaProperties">
        <prop key="hibernate.show_sql">${config.hibernate.show.sql}</prop>
        <prop key="hibernate.format_sql">${config.hibernate.show.sql}</prop>
        <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        <prop key="javax.persistence.validation.mode">none</prop>
        <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
        <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.SingletonEhCacheRegionFactory</prop>
        <prop key="hibernate.cache.provider_configuration">ehcache.xml</prop>
        <prop key="hibernate.cache.use_second_level_cache">true</prop>
        <prop key="hibernate.cache.use_query_cache">true</prop>
        <prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
    </util:properties>

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>

    <bean id="persistenceExceptionTranslationPostProcessor"
          class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

</beans>

spring配置檔案中
 <import resource="classpath*:persistenceContext.xml"/>