ssm(1-1)mybatis
1.概念
2.完全基于配置
2.1非接口式
mybatisBaseCongfig.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> <!--不能用classpath:以及/,也不能使用通配符--> <properties resource="dataresouce.properties"></properties> <settings> <!--驼峰式命名,例如t_id 会变为tId--> <setting name="mapUnderscoreToCamelCase" value="true"/> <!--设置日志管理文件,log4j的日志名称需要为LOG4J.xml放在类路径下--> <setting name="logImpl" value="LOG4J"/> <!--默认值为true,假如为false表示整个都不能使用二级缓存--> <setting name="cacheEnabled" value="true"/> <!--下列两个一起使用在某种程度上可以提高效率,但是懒加载在关闭session之后会存在异常--> <!--lazyLoadingEnabled为true 表示延迟加载--> <!--<setting name="lazyLoadingEnabled " value="true"/>--> <!--"aggressiveLazyLoading "为false表示按需加载,否则加载所有惰性属性--> <!--<setting name="aggressiveLazyLoading " value="fasle"/>--> </settings> <typeAliases> <!--别名,在mapper的文件中书写返回值参数和参数时,在其包下的可以是使用别名,类名小写--> <package name="cn.mybatis.bean"/> <!--单独别名,与上不能一起使用--> <!--<typeAlias type="cn.mybatis.bean.Department" alias="dept"/>--> </typeAliases> <!--default默认使用哪个environment id--> <environments default="mysql"> <environment id="mysql"> <!--type 2个值 JDBC 使用jdbc管理 manager 交由其他管理--> <transactionManager type="JDBC"/> <!--POOLED使用连接池继续 unpooled 不适用连接池 jndi 使用其他的连接池--> <dataSource type="POOLED"> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> </dataSource> </environment> </environments> <!-- type="DB_VENDOR" Vendordatabaseidprovider 作用就是根据不同厂商的标识,来标识执行不同的sql语句,如MYSQL,Oracle--> <databaseIdProvider type="DB_VENDOR"> <property name="MYSQL" value="mysql"></property> <property name="Oracle" value="oracle"></property> </databaseIdProvider> <mappers> <!--mapper接口的包,与其他两种不能共用--> <!--<package name="cn.mybatis.dao"/>--> <!--mapper.xml的文件,不能用classpath:以及/,也不能使用通配符--> <mapper resource="mapper/emp-mapper.xml" /> <!--mapper接口--> <!--<mapper class="cn.mybatis.dao.*"/>--> </mappers> </configuration>
mapper
<?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"> <!--该配置为非接口的方式,namespace可以随意的写--> <mapper namespace="a.b"> <!--默认二级缓存是关闭的, eviction缓存回收策略,4个参数如下: lru最近最少使用,移除最长时间不用的对象, fifo,先进先出的移除策略, soft,软引用, weak弱引用,默认使用LRU, type:使用其他类型的缓存,例如ehcache flushinterval:刷新时间,默认新的sql被执行时刷新缓存,insert 、update、delete 后缓存会被刷新清空, size缓存对象数量,默认值为1024, readonly:为true的话表示只读,不能修改,效率快不安全,false表示利用序列化和反序列化的技术,效率会低一些,但是安全, 默认是false,假如为false,那么bean需要实现序列化接口,查出的数据默认先放入一级缓存,只有在关闭会话以后才放入二级缓存, blocking:默认为false,当指定为true时将采用BlockingCache进行封装, 使用BlockingCache会在查询缓存时锁住对应的Key,如果缓存命中了则会释放对应的锁,否则会在查询数据库以后再释放锁, 这样可以阻止并发情况下多个线程同时查询数据。 --> <!--<cache readOnly="true" />--> <!--使用ehcache的二级缓存 ,配置文件名称为ehcache.xml,需要放在类路径下--> <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> <!--一个参数,参数类型可以不写,如下的#{id}的id可以随意写--> <!--<< ,>> ,& &, ' ', "" 针对性的特殊字符处理--> <!--<![CDATA[<]]> 处理特殊字符--> <!--该配置为非接口的方式,id可以随意的写--> <!-- 参数: resultType:返回值类型,这里在前面写了typeAliases package所以能这样写,否则全类名 parameterType:参数类型,可以时bean,可以时map(别名,见官方文档), statementType: 默认值prepared,还有statement与callable, usecache:true表示使用二级缓存,为false,表示不使用二级缓存 flushcache:true每次发送新的sql,增删改默认值为true,会刷新一级缓存和二级缓存,查询flushcache默认为false clearcache对1级缓存有作用,对二级无作用 databaseId="",指向databaseIdProvider的别名 timeout:等待数据库从请求返回的秒数。默认为未设置(依赖于驱动程序)。 resultMap:使用resultMap,指向resultMap的id --> <!--动态sql时,empId!=null,empId相当于#{empId}必须为属性--> <select id="getAll" resultType="employee" parameterType="employee" statementType="PREPARED" > select * from tab_emp <where> <choose> <when test="empId!=null"> and emp_id <![CDATA[<]]> #{empId} </when> <otherwise> and emp_id > 0 </otherwise> </choose> </where> </select> <!--直接获取参数1,当为数字时,设置参数没用,${id},id需要为对象中的属性--> <!--select * from tab_emp where emp_id=1 没有?直接填充--> <select id="getDifference1" resultType="employee" > select * from tab_emp where emp_id=${1} </select> <!--select * from tab_emp where emp_id = ? --> <!--一个参数,参数类型可以不写,如下的#{id}的id可以随意写--> <select id="getDifference2" resultType="employee" > select * from tab_emp where emp_id = #{1} </select> </mapper>
test
import cn.mybatis.bean.Employee; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import java.io.InputStream; import java.util.List; public class MybatisBaseTest { SqlSessionFactory ssf; @Before public void init(){ InputStream is = MybatisBaseTest.class.getResourceAsStream("/mybatisBaseCongfig.xml"); SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); ssf = ssfb.build(is); } @Test public void testDynamicsql(){ SqlSession ss = ssf.openSession(); Employee employee = new Employee(); employee.setEmpId(3); List<Object> list = ss.selectList("a.b.getAll",employee); System.out.println(list); } @Test public void getDifference1(){ SqlSession ss = ssf.openSession(); List<Object> list = ss.selectList("a.b.getDifference1",1); System.out.println(list); } @Test public void getDifference2(){ SqlSession ss = ssf.openSession(); List<Object> list = ss.selectList("a.b.getDifference2",1); System.out.println(list); } }
2.1半接口半配置
mybatisBaseCongfig.xml同上
mapper
<?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"> <!--namespace的cn.mybatis.dao.EmployeeImplMapper,必须与包名.类名一致--> <mapper namespace="cn.mybatis.dao.EmployeeImplMapper"> <!--id="getAll"的getAll必须与方法名一致,resultType="employee"多条自动装入集合--> <select id="getAll" resultType="employee" > select * from tab_emp where emp_id > #{1} </select> </mapper>
接口cn.mybatis.dao.EmployeeImplMapper
public interface EmployeeImplMapper { public List<Employee> getAll(Integer i); }
3.基于注解
3.1半注解半配置
mybatisBaseCongfig.xml同上,但是mappers中的mapper改为如下
接口
public interface EmployeeImplMapper { @Select("select * from tab_emp where emp_id > #{1} ")//也可以不是*,那么就是按需注入 public List<Employee> getAll(Integer i); }
去掉mybatisBaseCongfig.xml的mappers中的mapper,添加如下
<!--mapper接口的包,与其他两种不能共用--> <package name="cn.mybatis.dao"/>//指定某个包
也可以使用
<mapper class=""></mapper>//指定某个类
备注:<package name="cn.mybatis.dao"/>不能与<mapper class=""></mapper>及<mapper resource="" />一起使用
3.2完全基于注解(需要与spring整合)
4.整合spring
4.1基于配置文件的方式整合(顺带整合了分页以及批处理,log4j日志,mgb逆向)
dataresouce.properties
jdbc.user=root jdbc.password=123456 jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false&verifyServerCertificate=false jdbc.driver=com.mysql.cj.jdbc.Driver
application.xml
<?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:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--扫描的包--> <context:component-scan base-package="cn.mybatis"></context:component-scan> <!--添加资源--> <context:property-placeholder location="classpath:dataresouce.properties"></context:property-placeholder> <!--c3p0数据源--> <bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <!-- 其他的一些配置.... --> </bean> <!--mybatis--> <bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="comboPooledDataSource"></property> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> </bean> <!--mapper接口的加入到适配器中--> <bean id="configurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.mybatis.dao"></property> </bean> <!--批量处理--> <bean id="sessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sessionFactoryBean"></constructor-arg> <constructor-arg name="executorType" value="BATCH"></constructor-arg> </bean> <!--事务--> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="comboPooledDataSource"></property> </bean> <!--基于注解的方式--> <!--<tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>--> <!--基于配置的方式的事物--> <aop:config> <aop:pointcut id="pointcut" expression="execution(* cn.mybatis.service.*.*(..))"></aop:pointcut> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor> </aop:config> <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"> <tx:attributes> <tx:method name="*"/> <tx:method name="get*" read-only="true"></tx:method> </tx:attributes> </tx:advice> </beans>
mybatis-config.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> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="logImpl" value="LOG4J"></setting> </settings> <typeAliases> <package name="cn.mybatis"/> </typeAliases> <!--PageHelper 方法使用了 ThreadLocal ,分页参数和线程是绑定的。只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。 因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配, 导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。 --> <!--<property name="dialect" value="mysql"/>--> <!-- 该参数默认为false 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 --> <!-- 和startPage中的pageNum效果一样 --> <!--<property name="offsetAsPageNum" value="false"/>--> <!-- 该参数默认为false 设置为true时,使用RowBounds分页会进行count查询 --> <!--<property name="rowBoundsWithCount" value="true"/>--> <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 (相当于没有执行分页查询,但是返回结果仍然是Page类型), <property name="pageSizeZero" value="true"/> 3.3.0版本可用 ,分页参数合理化,默认false禁用 , 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 ,禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 --> <!--<property name="reasonable" value="true"/>--> <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法. 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 . 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 . 不理解该含义的前提下,不要随便复制该配置 <property name="params" value="pageNum=start;pageSize=limit;"/> --> <!--参数如上,还有一些键github的pagehelp的文档How to use PageHelper.--> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins> </configuration>
mgb逆向(官方文档 http://www.mybatis.org/generator/ )
<?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> <!--跟自定义的没关系--> <!--<classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" />--> <context id="DB2Tables" targetRuntime="MyBatis3"> <!--忽略注释--> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--连接数据库--> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&verifyServerCertificate=false&autoReconnct=true&autoReconnectForPools=true&allowMultiQueries=true&serverTimezone=GMT%2B8" userId="root" password="cgz12345678"> </jdbcConnection> <!--number是否转换为BigDecimal类型--> <javaTypeResolver > <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!--指定bean生成的位置--> <javaModelGenerator targetPackage="cn.mybatis.bean" targetProject="./mybatistest/src/main/java"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!--指定mapper文件生成的位置--> <sqlMapGenerator targetPackage="mapper" targetProject="./mybatistest/src/main/resources"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!--指定mapper接口生成的位置--> <javaClientGenerator type="XMLMAPPER" targetPackage="cn.mybatis.dao" targetProject="./mybatistest/src/main/java"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!--<table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" > <property name="useActualColumnNames" value="true"/> <generatedKey column="ID" sqlStatement="DB2" identity="true" /> 重新取字段名 <columnOverride column="DATE_FIELD" property="startDate" /> 忽略字段 <ignoreColumn column="FRED" /> <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> </table>--> <!--生成表,当时是多表关联时,手动的修改相应查询关系,见联表查询--> <table tableName="tab_emp" domainObjectName="Employee"></table> <table tableName="tab_dept" domainObjectName="Department"></table> </context> </generatorConfiguration>
log4j日志(LOG4J.xml)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration> <!--STDOUT表示输出 org.apache.log4j.ConsoleAppender 表示输出的类,这里表示输出到控制台--> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <!--表达式输出的字符集--> <param name="Encoding" value="UTF-8"/> <!--org.apache.log4j.PatternLayout 对象和与之相关的格式化的日志记录信息转换模式,这里表示表达式--> <layout class="org.apache.log4j.PatternLayout"> <!--ConversionPattern格式 --> <param name="ConversionPattern" value="%-5p %d{yyyy/MM/dd HH:mm:ss,SSS} %m %c (%F:%L) \n"/> </layout> </appender>
<appender name="file" class="org.apache.log4j.FileAppender"> <!--表达式输出的字符集--> <param name="Encoding" value="UTF-8"/> <!--Threshold=debug:指定日志消息的输出最低层次。--> <param name="Threshold" value="debug"/> <!--append:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容--> <param name="append" value="true"/> <!--File指定消息输出到mylog.txt文件。--> <param name="File" value="D:/logs/log4j.log"/> <!--ImmediateFlush:默认值是true,意谓着所有的消息都会被立即输出。--> <param name="ImmediateFlush" value="true"/> <!--org.apache.log4j.PatternLayout 对象和与之相关的格式化的日志记录信息转换模式,这里表示表达式--> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{yyyy/MM/dd HH:mm:ss,SSS} %m %c (%F:%L) \n"/> </layout> </appender> <!--指定包名下的输出级别--> <logger name="cn.mybatis.dao"> <level value="debug"/> </logger> <!--STDOUT的所有的输出级别 fatal(致命错误) > error (错误) > warn (警告) > info(普通信 息) > debug(调试信息) 如下为相应的name添加级别--> <root> <level value="warn"/> <appender-ref ref="STDOUT"/> <appender-ref ref="file"/> </root> </log4j:configuration>
test
import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.exception.XMLParserException; import org.mybatis.generator.internal.DefaultShellCallback; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class TestMBG { public static void main(String[] args) throws Exception{ String str = "mybatistest\\src\\main\\resources\\mbg.xml"; List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File(str); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } }
import cn.mybatis.bean.Employee; import cn.mybatis.bean.EmployeeExample; import cn.mybatis.dao.EmployeeMapper; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.junit.Test; import org.junit.runner.RunWith; 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; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.io.File; import java.sql.Connection; import java.util.ArrayList; import java.util.List; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:application.xml"}) public class MybatisTest { @Autowired ComboPooledDataSource comboPooledDataSource; @Autowired EmployeeMapper employeeMapper; @Test//c3p0测试 public void JdbcTest() throws Exception { Connection connection = comboPooledDataSource.getConnection(); System.out.println(connection); connection.close(); } @Test//mgb测试 public void TestMBGMybatis() throws Exception { //添加条件 EmployeeExample employeeExample = new EmployeeExample(); EmployeeExample.Criteria criteria = employeeExample.createCriteria(); criteria.andEmpIdEqualTo(1); List<Employee> employees = employeeMapper.selectByExample(employeeExample); for (Employee employee : employees) { System.out.println(employee); } } @Test//分页,添加了limit不是查询所有 public void TestPagehelper(){ PageHelper.startPage(1, 2); List<Employee> emps = employeeMapper.selectByExample(null); PageInfo<Employee> page = new PageInfo<>(emps); System.out.println(page); } }
4.2完全基于注解整合
5.连表查询
5.1 association(配置的方式)
非集合
mapper1.xml
<select id="getDept" resultType="cn.mybatis.bean.Department"> select * from tab_dept where dept_id=#{dept_id} </select>
mapper2.xml
<mapper namespace="cn.mybatis.dao.EmployeeMapper"> <resultMap id="BaseResultMap" type="cn.mybatis.bean.Employee"> <result column="emp_id" jdbcType="INTEGER" property="empId" /> <result column="emp_name" jdbcType="VARCHAR" property="empName" /> <result column="gender" jdbcType="TINYINT" property="gender" /> <result column="email" jdbcType="VARCHAR" property="email" /> <result column="dept_id" jdbcType="INTEGER" property="deptId" /> <association property="dept" column="dept_id" select="cn.mybatis.dao.DepartmentMapper.getDept"/>/*property属性名,column对应该表的列名的值,
select使用的那条select,是根据查表select * from students where id=#{0}(student)的column="tid"值查询teacher。*/ </resultMap>
test
@Test public void TestPagehelper(){ PageHelper.startPage(1, 2);//分页插件 List<Employee> emps = employeeMapper.selectByExample(null);//使用mbg逆向产生的类 PageInfo<Employee> page = new PageInfo<>(emps);//获取分页信息 System.out.println(page.getSize()); System.out.println(page.getStartRow()); System.out.println(page.isIsFirstPage()); System.out.println(page.isIsLastPage()); System.out.println(page.getPages()); System.out.println(page.getTotal()); List<Employee> list = page.getList(); System.out.println(list); }
5.2 集合 collection
<resultMap type="teacher" id="mymap">//resultMap需要与resultMap 的id名称一致,type表示返回值类型 <id column="id" property="id"/> <result column="name" property="name"/> <collection property="list" select="com.StudentMapper.selByTid" column="id"></collection> </resultMap> <select id="selAll" resultMap="mymap"> select * from teacher </select>
5.3 Auto Mapping
<resultMap type="Student" id="stuMap1"> <id column="sid" property="id"/> <result column="sname" property="name"/> <result column="age" property="age"/> <result column="tid" property="tid"/> <association property="teacher" javaType="Teacher" > <id column="tid" property="id"/> <result column="tname" property="name"/> </association> </resultMap> <select id="selAll1" resultMap="stuMap1"> select s.id sid,s.name sname,age age,t.idtid,t.name tname FROM student s left outer join teacher t on s.tid=t.id </select>
备注:对一的关系如上,查集合的时候上述方法不能使用,所以使用resultMap
5.4 注解
@Results(value={ @Result(id=true,property="id",column="id"), @Result(property="name",column="name"), @Result(property="list",column="id",many=@Many(select="com.StudentMapper.selByTid"))}) @Select("select * from teacher") List<Teacher> selTeacher();
备注:联表注解如上,其他注解类似基于注解的配置的注解
6.动态sql(参数需要是对象,单个参数可以不写参数类型,在配置中写别名减少参数类型的书写)
6.1 If 使用
<select id="selByAccinAccout" resultType="log"> select * from log where 1=1 <!-- OGNL 表达式,直接写key 或对象的属性.不需要添加任何特字符号--> <if test="accin!=null and accin!=''"> and accin=#{accin} </if> <if test="accout!=null and accout!=''"> and accout=#{accout} </if> </select>
6.2 where
<select id="selByAccinAccout" resultType="log"> select * from log <where> <if test="accin!=null and accin!=''"> and accin=#{accin} </if> <if test="accout!=null and accout!=''"> and accout=#{accout} </if> </where> </select>
备注:先去除第一个and 后添加where
6.3 <choose> <when> <otherwise>//只能有一个满足条件
<select id="selByAccinAccout" resultType="log"> select * from log <where> <choose> <when test="accin!=null and accin!=''"> and accin=#{accin} </when> <when test="accout!=null and accout!=''"> and accout=#{accout} </when> </choose> </where> </select>
6.4 <set>
<update id="upd" parameterType="log" > update log <set> id=#{id}, <if test="accIn!=null and accIn!=''"> accin=#{accIn}, </if> <if test="accOut!=null and accOut!=''"> accout=#{accOut}, </if> </set> where id=#{id} </update>
备注:先去除左右的逗号,然后添加set
6.5 Trim
prefix 在前面添加内容,prefixOverrides 去掉前面内容,suffix 在后面添加内容,suffixOverrieds 去掉后面内容执行顺序去掉内容后添加内容
<update id="upd" parameterType="log"> update log <trim prefix="set" suffixOverrides=","> a=a, </trim> where id=100 </update>
6.6 <bind>
<select id="selByLog" parameterType="log" resultType="log"> <bind name="accin" value="'%'+accin+'%'"/> #{accin} </select>
备注:在形成sql语句时,会在输入的地方添加为"'%'+accin+'%'"
6.7 <foreach>
<select id="selIn" parameterType="list"resultType="log"> select * from log where id in <foreach collection="list" item="abc" open="(" close=")" separator=","> #{abc} </foreach> </select>
备注:主要用于in中,open前添加,close后添加,separator分隔符,效率不高
7.一级缓存和二级缓存
7.1定义
mybatis 中的一级缓存,mybatis一级缓存的设置的范围是 Sqlsession级别(localCacheScope默认值为session,表示session作用范围,改变作用范围也可以达到关闭session),session的clearcache() 方法或者close 或者执行了 增删改方法则会清除一级缓存,但是对二级缓存没有影响;mybatis 的二级缓存是配置文件范围的或者说命名空间范围,默认是关闭的(不安全),默认insert 、update、delete 后一级和二级缓存会被刷新,查询时sql没变的前提下不会刷新缓存,直接冲缓存中读取数据,不会发送sql,缓存的查找先从二级缓存中寻找后到一级缓存中寻找,缓存的保存先保存在一级缓存后到二级缓存,mybatis使用的二级缓存使用的是map储存,参数及其它含义见前面的配置中的参数说明
7.2自定义二级缓存(ehcache的官方文档 http://www.mybatis.org/ehcache-cache/)
由于mybatis使用的二级缓存使用的是map储存不专业,一般我们会交给ehcache来处理二级缓存,不论是ehcahe还是memcached等
配置在mapper.xml中配置相应
<!--使用ehcache的二级缓存 ,配置文件名称为ehcache.xml,需要放在类路径下--> <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
ehcache.xml(需要放在类路径下)
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 磁盘保存路径 --> <diskStore path="D:\cache\ehcache" /> <defaultCache maxElementsInMemory="10000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache> <!-- 属性说明: diskStore:指定数据在磁盘中的存储位置。 defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略 以下属性是必须的: maxElementsInMemory - 在内存中缓存的element的最大数目 maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大 eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断 overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上 以下属性是可选的: timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大 timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大 diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区. diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。 diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作 memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
也可以按如下配置
8.其他
8.1 自定义类型转换器(基本不用)
org.apache.ibatis.type.TypeAliasRegistry 别名的源码类,自定义类转换器可以继承BaseTypeHandler<T>类(已有类型见官方文档),书写可参考,BaseTypeHandler看源码,ctrl+t,找实现的子类,例如StringTypeHandler,参照写,假如看不懂,那么把该源代码复制建立在相同的包下,那么调用的时候会先调用本地的,然后在其中输出相应的参数就可以知道了。
<insert id="insertUser" parameterType="User">
insert into t_user(id,accountID,userName,statusDef,statusOrdinal,statusCustom)
values(
#{id}, #{accountID}, #{userName},
#{statusDef},
#{statusOrdinal, typeHandler=com.util.typehandler.xxxTypeHandler},
#{statusCustom, typeHandler=com.util.typehandler.xxxTypeHandler}
)
</insert>
8.2 分页:mybatis是不能对ognl表达式进行运算符运算的,如右select * from people limit #{pageStart},#{pageSize}
8.3 Configuration.class文件中含有相应的配置以及别名等(配置文件中的别名)
8.4 获取自增主键<insert id="insertOne" parameterType="cn.mybatis3.test.Person1" useGeneratedKeys="true" keyProperty="id">,useGeneratedKeys设置为true,默认值为false,keyProperty表示映射到bean的person1的id属性
8.5 collection多值传递
<collection
property="list" select="com.StudentMapper.selByTid"
column="id"></collection>中的column可以写成
column={key=value,key1=value1...}的形式,
延迟加载可以在其中添加fetchType="lazy",eager表示立即加载
8.6 鉴别器(基本不用)
<discriminator javaType="string" column="age"> <case value="0" resultType=""> <collection property=""></collection> </case> <case value="1" resultType=""> </case> </discriminator>
8.7关联本地dtd,window --- references---xml----xmlcatalog--add,在idea中也有类似的关联
附录:maven依赖(批量处理(sqlsessiontemplate),分页(pagehelper),mgb逆向(generator),修改mgb的mapper文件实现联表查询,ehcache缓存,log4j日志)
<?xml version="1.0" encoding="UTF-8"?> <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>cn.mybatis.test</groupId> <artifactId>mybatistest</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <springframework.version>5.1.0.RELEASE</springframework.version> </properties> <dependencies> <!--spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <!--spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${springframework.version}</version> </dependency> <!--spring-test--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${springframework.version}</version> <scope>test</scope> </dependency> <!--spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${springframework.version}</version> </dependency> <!--mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--mybatis与spring整合--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <!--c3p0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <!--mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.12</version> </dependency> <!-- junit依赖,scope为test所以是灰色的 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--mgb逆向--> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.7</version> </dependency> <!--二级缓存用的不是很多,可以不开启--> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.1.0</version> </dependency> <!--pagehelper分页--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.6</version> </dependency> <!--日志包--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> <encoding>${project.build.sourceEncoding}</encoding> </configuration> </plugin> </plugins> </build> </project>