二级缓存及高级映射
sqlMapConfig.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> <properties resource="dbSources.properties"></properties> <!-- 通过resultMap实现延迟加载 --> <settings> <!-- 打开延迟加载的开关 ,默认是false--> <setting name="lazyLoadingEnabled" value="true"/> <!-- 将积极加载改为消极加载即按需要加载,默认为true --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 开启二级缓存 默认值为true--> <setting name="cacheEnabled" value="true" /> </settings> <typeAliases> <typeAlias type="com.chen.pojo.OrderCustom" alias="_OrderCustom"></typeAlias> <typeAlias type="com.chen.pojo.Orders" alias="_Order"></typeAlias> <typeAlias type="com.chen.pojo.Orderdetail" alias="_OrderDetail"></typeAlias> <typeAlias type="com.chen.pojo.Goods" alias="_Goods"></typeAlias> <typeAlias type="com.chen.pojo.User" alias="_User"></typeAlias> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <package name="com.chen.mapper"/> </mappers> </configuration>
二级缓存mapper.xml
<?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.chen.mapper.UserMapper"> <!-- 开启本mapper的二级缓存 type:指定cache接口的实现类的类型,默认使用PerpetualCache 要和ehcache整合,需要配置type为ehcache的实现类 --> <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> <!-- useCache设置是否禁用二级缓存 --> <select id="findUserById" parameterType="int" resultType="_User" > select * from t_user where id=#{id} </select> <!-- flushCache设置是否执行刷新缓存 flushCache="false"--> <update id="updateUserById" parameterType="_User" > update t_user set username=#{username},birthday=#{birthday},sex=#{sex} where id=#{id} </update> </mapper>
高级映射mapper.xml
<?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.chen.mapper.OrderMapperCustom"> <select id="findOrderUser" resultType="_OrderCustom"> select o.user_id userid,o.number number,o.create_time createtime,o.note note,u.username,u.birthday,u.sex from t_order o,t_user u where o.user_id = u.id </select> <select id="findOrderUser2" resultMap="OrderResultMap"> select o.*,u.id u_id,u.username,u.birthday,u.sex from t_order o,t_user u where o.user_id = u.id </select> <resultMap type="_Order" id="OrderResultMap"> <id property="id" column="id"/> <result property="userId" column="user_id"/> <result property="number" column="number"/> <result property="createtime" column="create_time"/> <result property="note" column="note"/> <association property="user" javaType="_User"> <id property="id" column="u_id"/> <result property="username" column="username"/> <result property="birthday" column="birthday"/> <result property="sex" column="sex"/> </association> </resultMap> <select id="findOrderDetail" resultMap="DetailResultMap"> select o.*,u.id u_id,u.username,u.birthday,u.sex,d.id d_id,d.goods_id,d.order_id,d.goods_count from t_order o,t_user u,t_ordertail d where o.user_id = u.id and d.order_id=o.id </select> <resultMap type="_Order" id="DetailResultMap"> <id property="id" column="id"/> <result property="userId" column="user_id"/> <result property="number" column="number"/> <result property="createtime" column="create_time"/> <result property="note" column="note"/> <association property="user" javaType="_User"> <id property="id" column="u_id"/> <result property="username" column="username"/> <result property="birthday" column="birthday"/> <result property="sex" column="sex"/> </association> <collection property="orderdetails" ofType="_OrderDetail"> <id property="id" column="d_id"/> <result property="goodsId" column="goods_id"/> <result property="orderId" column="order_id"/> <result property="goodsCount" column="goods_count"/> </collection> </resultMap> <select id="findOrderGoods" resultMap="GoodsResultMap"> select o.*,u.id u_id,u.username,u.birthday,u.sex,d.id d_id,d.goods_id,d.order_id,d.goods_count, g.id g_id,g.name ,g.detail,g.createtime,g.price from t_order o,t_user u,t_ordertail d,t_goods g where o.user_id = u.id and d.order_id=o.id and d.goods_id = g.id </select> <resultMap type="_Order" id="GoodsResultMap"> <id property="id" column="id"/> <result property="userId" column="user_id"/> <result property="number" column="number"/> <result property="createtime" column="create_time"/> <result property="note" column="note"/> <association property="user" javaType="_User"> <id property="id" column="u_id"/> <result property="username" column="username"/> <result property="birthday" column="birthday"/> <result property="sex" column="sex"/> </association> <collection property="orderdetails" ofType="_OrderDetail"> <id property="id" column="d_id"/> <result property="goodsId" column="goods_id"/> <result property="orderId" column="order_id"/> <result property="goodsCount" column="goods_count"/> <association property="goods" javaType="_Goods"> <id property="id" column="g_id"/> <result property="name" column="name"/> <result property="detail" column="detail"/> <result property="createtime" column="createtime"/> <result property="price" column="price"/> </association> </collection> </resultMap> <select id="findOrderUserLazy" resultMap="OrderLazyResultMap"> select * from t_order </select> <resultMap type="_Order" id="OrderLazyResultMap"> <id property="id" column="id"/> <result property="userId" column="user_id"/> <result property="number" column="number"/> <result property="createtime" column="create_time"/> <result property="note" column="note"/> <association property="user" javaType="_User" column="user_id" select="com.chen.mapper.UserMapper.findUserById"> </association> </resultMap> </mapper>
二级应用场景
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
二级缓存局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
整合spring
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> <!-- 加载配置文件 --> <context:property-placeholder location="classpath:dbSources.properties"/> <!-- 配置数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置sessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 加载mybatis的配置文件 --> <property name="configLocation" value="mybatis/sqlMapConfig.xml" /> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 第一种方式,通过dao实现类方式 --> <bean id="userDao" class="com.chen.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean> <!-- 第二种方式,通过mapper代理 (单个mapper)--> <!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.chen.mapper.UserMapper"></property> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> --> <!-- 第二种方式,通过mapper代理,(批量) --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.chen.mapper" /> <!-- 必须用 sqlSessionFactoryBeanName,否则dbSources.properties无法加载,会先执行当前注入--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> </beans>
反向工程
配置文件generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="root" password="root"> </jdbcConnection> <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" userId="yycg" password="yycg"> </jdbcConnection> --> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成PO类的位置 --> <javaModelGenerator targetPackage="com.chen.pojo" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.chen.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.chen.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定数据库表 --> <table tableName="t_user" domainObjectName="User"></table> <table tableName="t_order" domainObjectName="Order"></table> <table tableName="t_orderdetail" domainObjectName="OrderDetail"></table> <table tableName="t_goods" domainObjectName="Goods"></table> <!-- 有些表的字段需要指定java类型 <table schema="" tableName=""> <columnOverride column="" javaType="" /> </table> --> </context> </generatorConfiguration>
生成代码 GeneratorSqlmap.java
package com.chen.demo; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; public class GeneratorSqlmap { public void generator() throws Exception{ List<String> warnings = new ArrayList<String>(); boolean overwrite = true; //File configFile = new File("generatorConfig.xml"); InputStream is = GeneratorSqlmap.class.getClassLoader().getResourceAsStream("generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(is); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap(); generatorSqlmap.generator(); } catch (Exception e) { e.printStackTrace(); } } }