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)
"/>
</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)
"/>
</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:cacheehcache" />
<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>