Java SE MyBatis框架(详解)
Java SE MyBatis框架
目录
- Java SE MyBatis框架
- 通用框架
- 1.lib
- 2、src
- 2.1、mybatis.xml
- 2.2、DateBase.properties
- 2.3、log4j.properties
- 2.4、generatorConfig.xml
- 2.5、mapper包
- 2.6、pojo包
- 2.7、utils包
- 1、框架介绍
- 2、Mybatis特点
- My Batis功能架构图:
- 3、Mybatis环境搭建
- 3.1、新建Java项目
- 3.2、导入jar包
- 3.3、Mybatis配置文件
- 3.3.1、dtd
- 3.3.2、mybatis.xml文件配置内容:
- 3.3.2.2、通过properties标签实现软编码
- 3.3.3、 SQL映射文件 mapper.xml
- 3.4、测试
- 4、Mybatis配置文件详解
- 4.1、Mybatis.xml核心配置文件
- 4.2、SQL映射文件(mapper)
- 1、mapper
- 2.select
- 2.1、三个查询方法
- 3、insert – 映射插入语句
- 4、update – 映射更新语句
- 5、delete – 映射删除语句
- 5、Log4j日志
- 5.1、 日志级别
- 5.2、使用
- 5.2.1、配置文件
- 5.3、常见日志输出格式
- 6、typeAliases标签---Mybatis核心文件下
- 6.1、使用方式
- 6.2. Mybatis的内建别名
- 7、parameterType入参类型---mapper.xml
- 7.3、入参类型
- 7.3.3. JavaBean
- 7.3.4. Map
- 9、工具类的封装 utils
- 10、事务
- 11、接口绑定方案
- 11.1、实现方式
- 11.1.1、定义接口
- 11.1.2、映射文件
- 11.2、接口代理开发CRUD
- 11.2.3、批量操作
- 12、动态SQL
- 12.1、if
- 12.2、where
- 12.3、choose...when...otherwise
- 12.4、set
- 12.5、trim
- 12.6、bind
- 12.7、foreach
- 12.8、sql...include
- 13、Mybatis缓存机制
- 13.1、一级缓存
- 13.2、二级缓存
- 14、关系映射
- 14.1、 resultMap的关联方式实现多表查询(一对一|多对一)
- 14.2、resultMap的关联方式实现多表查询(一对 多)
- 14.3、列名和属性名不一致问题
- 15、注解开发
- 15.1、MyBatis中常用的注解
- 16、逆向工程
通用框架
1.lib
导包
2、src
2.1、mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--dtd约束: 核心配置文件中内容的定义-->
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根节点-->
<configuration><!-- 加载外部的properties文件 --><properties resource="DateBase.properties" /><!-- settings标签 --><settings><!-- 设置MyBatis使用log4j日志支持 --><setting name="logImpl" value="LOG4J"/></settings><typeAliases><!--<typeAlias type="com.xxxx.pojo.Dept" alias="dept"/>--> <!--不区分大小写--><!--<typeAlias type="com.xxxx.pojo.Dept"/> --> <!--默认类型别名为类名,不区分大小写--><package name="mybatis.week.pojo"/> <!-- 包下所有的类默认类名 -->
<!-- <package name="mybatis.week2.pojo"/>--></typeAliases><!--环境的配置default : 选择当前要使用的环境->不同环境的id--><environments default="dev"><!--环境的定义 id : 当前环境的唯一标识 --><environment id="dev"><!--transactionManager : 事务管理器type : 当前mybatis使用哪种事务管理机制JDBC : 与JDBC相同的事务管理方式 --><transactionManager type="JDBC"/><!--dataSource: 数据库连接参数的配置|连接池type : 是否使用数据库连接池POOLED : 使用连接池技术--><dataSource type="POOLED"><!--property : 连接参数选项的配置--><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--SQL映射文件的加载配置: --><mappers><!--resource : sql映射文件的路径-->
<!-- <mapper resource="mybatis/week/mapper/DeptMapper.xml"/>--><!--指定接口绑定方案中的接口: 接口的权限定名: 包名.接口名-->
<!-- <mapper class="mybatis.week.mapper.StudentMapper0"/>--><!--配置指定包下的所有接口--><package name="mybatis.week.mapper"/><!-- <mapper resource="mybatis/week2/mapper/StudentMapper.xml"/>--></mappers></configuration>
2.2、DateBase.properties
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:ORCL
username=SCOTT
password=TIGER
2.3、log4j.properties
# Set root category priority to INFO and its only appender to CONSOLE.
#additivity="false"
log4j.rootCategory=ERROR,CONSOLE
log4j.logger.mybatis.week.mapper=DEBUG
# log4j.rootCategory=INFO, CONSOLE, LOGFILE# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:/test.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=- %m %l%n
2.4、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="Tables" targetRuntime="MyBatis3"> <!-- 生成的Java文件的编码 --><property name="javaFileEncoding" value="UTF-8" /> <!-- JavaBean 实现 序列化 接口 --> <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/> <commentGenerator><property name="suppressDate" value="true" /><!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="false" /></commentGenerator> <!--数据库链接地址账号密码 --><jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@localhost:1521:xe" userId="SCOTT" password="TIGER"> </jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true 时把 JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --><javaTypeResolver><property name="forceBigDecimals" value="false" /> </javaTypeResolver><!--生成 Model 类存放位置 --> <javaModelGenerator targetPackage="com.xxxx.pojo" targetProject="mybatis12\src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!--生成映射文件存放位置 --> <sqlMapGenerator targetPackage="com.xxxx.mappers" targetProject="mybatis12\src"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!--生成接口类存放位置(Dao|Mapper) --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.xxxx.mappers" targetProject="mybatis12\src"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 参考数据库中需要生成的对应表信息 --> <table tableName="dept" domainObjectName="Dept" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="emp" domainObjectName="Emp" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context>
</generatorConfiguration>
2.5、mapper包
SQL映射文件(mapper).xml
所对应的mapper.xml的接口文件
2.6、pojo包
Javabean文件
2.7、utils包
封装工具类
1、框架介绍
MyBatis 本是apache的一个开源项目iBatis,后迁移到了 google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO) MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。
MyBatis消除了几乎所有的 JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和 原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
Mybatis不是一个完全的orm框架,Mybatis需要程序员自己写sql,但是也存在映射(输入参数映射,输 出结果映射),学习门槛mybatis比hibernate低;同时灵活性高,特别适用于业务模型易变的项目,使 用范围广。
简单概括:
更加简化jdbc代码,简化持久层,sql语句从代码中分离,利用反射,将表中数据与java bean 属性一一 映射 即 ORM(Object Relational Mapping 对象关系映射)
使用范围:
在日常的开发项目中,如中小型项目,例如ERP,需求与关系模型相对固定建议使用Hibernate,对于需 求不固定的项目,比如:互联网项目,建议使用mybatis,因为需要经常灵活去编写sql语句。总之, mybatis成为当下必须学习掌握的一个持久层框架。
2、Mybatis特点
属于持久层ORM框架
1.持久层: 讲内存中对象数据,转移到数据库中的过程持久层
Mybatis ;Hibernate; Spring-jpa
2、ORM Object Relational Mapping 对象关系映射框架
- 类—》 表
- 属性—》 字段
- 对象—》 记录
3、半自化 自动化
Mybatis 半自动化
- 表需要手动进行设计
- 提供sql
- 表需要手动进行设计提供sql
- 依赖与数据库平台
- 优点:学习使用简单(基与原声jdbc封装),优化灵活,适合做互联网项目
Hibernate 自动化ORM框架
- 表可以通过框架自动创建省略一些基本的sql
- 不依赖与数据库平台
- 缺点: 学生成本高,优化难度大,适合与传统框(OA|图书管理系统…),不适合做大型互联网项目
My Batis功能架构图:
3、Mybatis环境搭建
官网: https://mybatis.org/mybatis-3/zh/index.html
3.1、新建Java项目
新建Java项目,导入核心java包与mybatis依赖jar包
3.2、导入jar包
选中所有的jar包,右键build path->add to build path 管理外部的jar资源
3.3、Mybatis配置文件
mybatis提供两种配置文件:
- 核心配置文件 mybatis-config.xml 或mybatis.xml
- SQL映射文件mapper.xml
核心配置文件是一个xml文件,命名无要求,位置无要求,一般成为mybatis.xml,放在src路径下
3.3.1、dtd
- \1. 解压mybatis核心jar包,找到本地dtd文件
- \2. ide工具中关联mybatis配置文件的dtd约束
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
3.3.2、mybatis.xml文件配置内容:
硬解码:
<?xml version="1.0" encoding="UTF-8" ?>
<!--dtd约束: 核心配置文件中内容的定义-->
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根节点-->
<configuration><!-- settings标签 --><settings><!-- 设置MyBatis使用log4j日志支持 --><setting name="logImpl" value="LOG4J"/></settings><typeAliases><!--<typeAlias type="com.xxxx.pojo.Dept" alias="dept"/>--> <!--不区分大小写--><!--<typeAlias type="com.xxxx.pojo.Dept"/> --> <!--默认类型别名为类名,不区分大小写--><package name="mybatis.week.pojo"/> <!-- 包下所有的类默认类名 --><package name="mybatis.week2.pojo"/></typeAliases><!--环境的配置default : 选择当前要使用的环境->不同环境的id--><environments default="dev"><!--环境的定义 id : 当前环境的唯一标识 --><environment id="dev"><!--transactionManager : 事务管理器type : 当前mybatis使用哪种事务管理机制JDBC : 与JDBC相同的事务管理方式--><transactionManager type="JDBC"/><!--dataSource: 数据库连接参数的配置|连接池type : 是否使用数据库连接池POOLED : 使用连接池技术--><dataSource type="POOLED"><!--property : 连接参数选项的配置--><property name="driver" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/> <property name="username" value="SCOTT"/> <property name="password" value="TIGER"/></dataSource></environment></environments><!--SQL映射文件的加载配置: --><mappers><!--resource : sql映射文件的路径--><mapper resource="mybatis/week/mapper/DeptMapper.xml"/><mapper resource="mybatis/week/mapper/DeptMapper2.xml"/><mapper resource="mybatis/week/mapper/EmpMapper.xml"/><mapper resource="mybatis/week2/mapper/StudentMapper.xml"/></mappers>
</configuration>
3.3.2.2、通过properties标签实现软编码
src下定义配置文件db.properties
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=SCOTT
password=TIGER
mybatis核心配置文件中添加properties标签,指定加载外部的properties文件,注意定义位置
<!-- 加载外部的properties文件 -->
<properties resource="db.properties" />
获取properties文件中数据时候,要通过${}的方式获取
ironments default="even"> <environment id="even"> <transactionManager type="JDBC"></transactionManager><dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/><property name="password" value="${password}"/> </dataSource></environment> </environments>
s
3.3.3、 SQL映射文件 mapper.xml
在Mybatis中,推荐使用mappers作为包名,我们只需要写一个映射配置文件就可以,Mapper.xml,用于定义要执行的sql语句,同时可以设置参数|返回值结果类型。
注意:不要忘记mybatis核心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"><!--跟标签mapper namespace: 命名空间--> <mapper namespace="com.xxxx.mappers.UserMapper"><!--查询标签: select 用于编写查询语句 id : 当前文件中保证唯一 resultType : 结果的类型 parameterType : 入参类型 --> <select id="queryAll" resultType="com.xxxx.pojo.User"> select * from t_user </select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace : 命名空间在当前项目下,namespace的值是唯一的,不能重复的,SQL映射文件的唯一标识定义:1.任意定义,不重复,唯一即可2.建议: 包名.文件名 (不加后缀名) ->推荐-->
<mapper namespace="mybatis.week.mapper.DeptMapper"><!--select标签: 定义查询sql语句 ->Statementid : 在当前命名空间中,不能存在2个标签的id属性值相同,标签的唯一标识resultType : 结果类型引用数据类型: 类型的权限定名 包名.类名集合: 泛型类型parameterType : 入参类型基本数据类型|包装类 javabean 数组,list,map--><select id="queryAll" resultType="Dept">SELECT * FROM DEPT</select><!--根据部门编号查询部门信息--><select id="queryDeptToNo" parameterType="int" resultType="Dept">SELECT DEPTNO,DNAME,LOC FROM DEPT WHERE DEPTNO = #{DEPTNO}</select></mapper>
3.4、测试
public class TestUser { public static void main(String[] args) throws IOException { //1.加载mybatis全局核心配置文件 InputStream is = Resources.getResourceAsStream("mybatis.xml"); //2.构建SqlSessionFactory对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂获取会话SqlSession SqlSession session = factory.openSession(); //4.通过session调用方法执行查询 //selectList() 查到的数据返回一个list集合,没查到返回空的list //selectList 的第一个参数为statement: 命名空间+id List<User> list = session.selectList("com.xxxx.mappers.UserMapper.queryAll"); System.out.println(list); //5.关闭会话资源 session.close(); } }
import mybatis.week.pojo.Dept;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
import org.apache.log4j.lf5.util.Resource;import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.*;public class DeptCode01 {public static void main(String[] args) throws IOException {//加载执行核心配置文件InputStream ips =Resources.getResourceAsStream("mybatis.xml");//2.构建SqlSessionFactorySqlSessionFactory factory=new SqlSessionFactoryBuilder().build(ips);//3根据工厂获取回话SqlSession session=factory.openSession();//4、执行指定的sql//selectList("命名空间.id")List<Dept> list =session.selectList("mybatis.week.mapper.DeptMapper.queryAll");//根据部门 编号查询部门信息//selectOne("命名空间.id")//selectOne("命名空间.id",入参)Dept dept=session.selectOne("mybatis.week.mapper.DeptMapper.queryDeptToNo",10);//selectMap("命名空间.id","作为key的字段名")//selectMap("命名空间.id",入参,"作为key的字段名")Map<Integer,Dept> map=session.selectMap("mybatis.week.mapper.DeptMapper.queryAll","deptno");//5.处理数据list.forEach(System.out::println);System.out.println("___________________");System.out.println(dept);System.out.println("____________________");System.out.println(map);//6.关闭回话session.close();}
}
4、Mybatis配置文件详解
4.1、Mybatis.xml核心配置文件
1、configuration
配置文件的根元素,所有其他的元素都要在这个标签下使用(dtd文件规定)
2、environments default="environment"
用于管理所有环境, 并可以指定默认使用那个环境,通过defualt属性来指定
3、environment
用来配置环境,id属性用于唯一标识当前环境
4、transactionManager type="JDBC"
用户配置事务管理器
type属性
用来指定Mybatis采用何种方式管理事务
JDBC : 表示采用与原生JDBC一致方式管理事务
MANAGED: 表示讲事务管理交给其他容器进行, Spring
5、dataSource type="POOLED"
用于配置数据源, 设置Myabtis是否使用连接池技术,并且配置数据库的四个连接参数
type属性:
POOLED : 表示采用连接池技术
UNPOOLED: 表示每次都会开启和关闭连接, 不采用连接池技术
JNDI : 使用其他容器提供数据源
6、property
用于配置数据库连接参数 (driver,url,username,password)
7、Mappers
用于配置扫描sql映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--dtd约束: 核心配置文件中内容的定义-->
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根节点-->
<configuration><!-- 加载外部的properties文件 --><properties resource="DateBase.properties" /><!-- settings标签 --><settings><!-- 设置MyBatis使用log4j日志支持 --><setting name="logImpl" value="LOG4J"/></settings><typeAliases><!--<typeAlias type="com.xxxx.pojo.Dept" alias="dept"/>--> <!--不区分大小写--><!--<typeAlias type="com.xxxx.pojo.Dept"/> --> <!--默认类型别名为类名,不区分大小写--><package name="mybatis.week.pojo"/> <!-- 包下所有的类默认类名 -->
<!-- <package name="mybatis.week2.pojo"/>--></typeAliases><!--环境的配置default : 选择当前要使用的环境->不同环境的id--><environments default="dev"><!--环境的定义 id : 当前环境的唯一标识 --><environment id="dev"><!--transactionManager : 事务管理器type : 当前mybatis使用哪种事务管理机制JDBC : 与JDBC相同的事务管理方式--><transactionManager type="JDBC"/><!--dataSource: 数据库连接参数的配置|连接池type : 是否使用数据库连接池POOLED : 使用连接池技术--><dataSource type="POOLED"><!--property : 连接参数选项的配置--><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--SQL映射文件的加载配置: --><mappers><!--resource : sql映射文件的路径-->
<!-- <mapper resource="mybatis/week/mapper/DeptMapper.xml"/>--><!--指定接口绑定方案中的接口: 接口的权限定名: 包名.接口名-->
<!-- <mapper class="mybatis.week.mapper.StudentMapper0"/>--><!--配置指定包下的所有接口--><package name="mybatis.week.mapper"/><!-- <mapper resource="mybatis/week2/mapper/StudentMapper.xml"/>--></mappers></configuration>
4.2、SQL映射文件(mapper)
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射查询语句
查询语句是 MyBatis 中最常用的元素之一(映射文件配置见代码)
1、mapper
SQL映射文件的根元素
namespace 属性:
用于指定命名空间, 通过namespace+id的方式用来定位sql语句
namespace的值是唯一的,SQL映射文件的唯一标识
定义:
1.任意定义,不重复,唯一即可
2.建议: 包名.文件名 (不加后缀名) ->推荐
<mapper namespace="mybatis.week.mapper.DeptMapper">
2.select
用来定义查询语句 update insert delete
- id 属性
- 用阿里唯一表示当前sql语句,在当前的命名空间中唯一,不能重复 , 类型方法名resultType 属性
- 用于设定查询返回的结果的数据类型,要写类型的权限定名(包名+类名),如果返回值的是集合类型,要定义集合的泛型类型
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace : 命名空间在当前项目下,namespace的值是唯一的,不能重复的,SQL映射文件的唯一标识定义:1.任意定义,不重复,唯一即可2.建议: 包名.文件名 (不加后缀名) ->推荐-->
<mapper namespace="mybatis.week.mapper.DeptMapper"><!--select标签: 定义查询sql语句 ->Statementid : 在当前命名空间中,不能存在2个标签的id属性值相同,标签的唯一标识resultType : 结果类型引用数据类型: 类型的权限定名 包名.类名集合: 泛型类型parameterType : 入参类型基本数据类型|包装类 javabean 数组,list,map--><select id="queryAll" resultType="Dept">SELECT * FROM DEPT</select><!--根据部门编号查询部门信息--><select id="queryDeptToNo" parameterType="int" resultType="Dept">SELECT DEPTNO,DNAME,LOC FROM DEPT WHERE DEPTNO = #{DEPTNO}</select></mapper>
2.1、三个查询方法
- selectList(“命名空间.id”) 用户查询多条数据情况,返回一个List集合, 没有查到数据返回空集合,不是null
- selectOne(“命名空间.id”) 用于查询单条数据,返回一个数据, 如果没有查到返回null
- selectMap(“命名空间.id”,key的字段名) 用于查询多条记录情况, 返回Map集合, 需要指定那个属性作为key, sql查询结果作为value,指定的字段值作为key, 如果查不到, 返回一个空map集合,不是null
//加载执行核心配置文件InputStream ips =Resources.getResourceAsStream("mybatis.xml");//2.构建SqlSessionFactorySqlSessionFactory factory=new SqlSessionFactoryBuilder().build(ips);//3根据工厂获取回话SqlSession session=factory.openSession();//4、执行指定的sql//selectList("命名空间.id")List<Dept> list =session.selectList("mybatis.week.mapper.DeptMapper.queryAll");//根据部门 编号查询部门信息//selectOne("命名空间.id")//selectOne("命名空间.id",入参)Dept dept=session.selectOne("mybatis.week.mapper.DeptMapper.queryDeptToNo",10);//selectMap("命名空间.id","作为key的字段名")//selectMap("命名空间.id",入参,"作为key的字段名")Map<Integer,Dept> map=session.selectMap("mybatis.week.mapper.DeptMapper.queryAll","deptno");//5.处理数据list.forEach(System.out::println);System.out.println("___________________");System.out.println(dept);System.out.println("____________________");System.out.println(map);//6.关闭回话session.close();
3、insert – 映射插入语句
4、update – 映射更新语句
5、delete – 映射删除语句
增删改需要提交事务,session.commit();
mapper.xml
<!-- 测试增删改 : 结果返回的都是影响函数int --><!-- 新增 --><insert id="insertStudent" parameterType="student">insert into student values(#{arg0},#{arg1},#{arg2},#{arg3},#{arg4})</insert><!-- 修改 --><update id="updateStudent" parameterType="student">update student set sage = #{param1} where sno =#{param2}</update><!-- 删除 --><delete id="deleteStudent" parameterType="_int">delete from student where sno = #{arg0}</delete>
test.java
//1.获取会话SqlSession session= BatisUtils.getSession();//2.获取接口的实现类对象StudentMapper0 mapper = session.getMapper(StudentMapper0.class);//3.调用方法//添加信息int rows=0;//rows =mapper.insertStudent(10001,"张三","男",22,"数学系");System.out.println("-------------------------------------------------------");//修改信息//rows=mapper.updateStudent(20,1000);System.out.println("-------------------------------------------------------");//删除数据/* rows=mapper.deleteStudent(1000);if (rows>0){System.out.println("成功");}else{System.out.println("失败");}*/
5、Log4j日志
日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录。
5.1、 日志级别
分为五个级别:
- DEBUG(人为调试信息)
- INFO(普通信息)
- WARN(警告)
- ERROR(错误)
- FATAL(系统错误)
这五个级别是有顺序的,DEBUG < INFO < WARN < ERROR < FATAL,分别用来指定这条日志信息的重要程度。
Log4j有一个规则:只输出级别不低于设定级别的日志信息,假设Loggers级别设定为INFO,则INFO、WARN、ERROR和FATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。
5.2、使用
导包,
在Mybatis.xml中< properties >后添加t
<!-- settings标签 -->
<settings> <!-- 设置MyBatis使用log4j日志支持 --> <setting name="logImpl" value="LOG4J"/>
</settings>
5.2.1、配置文件
可以使用properties或者xml进行配置,使用一个叫 log4j.properties 的配置文件, 会设定 log4j的设置信息, 例如日志级别, 日志输出方式, 日志格式等等
# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootCategory=INFO, CONSOLE
# log4j.rootCategory=INFO, CONSOLE, LOGFILE # CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=- %m %c %l %d{yyyy-MMdd HH:mm:ss}%n # LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=d:/test.log
log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=- %m %l%n
局部调整:
# 提高整体日志级别
log4j.rootCategory=ERROR, CONSOLE
# 单独设置SQL语句的输出级别为DEBUG级别
# 方法级别
# log4j.logger.com.xxxx.mapper.UserMapper.selAll=DEBUG
# 类级别
# log4j.logger.com.xxxx.mapper.UserMapper=DEBUG
# 包级别
log4j.logger.com.xxxx.mapper=DEBUG
5.3、常见日志输出格式
参数 | 描述 | 实例 |
---|---|---|
c <> | 输出Logger所在的类别(即Logger的名字)。允许使用%c{数字}输出部分的名字(从右边往左边数)。见实例 | %c将输出com.log4j.Log4jTest %c{1}将输出Log4jTest %c{2}将输出log4j.Log4jTest %c{3}将输出com.log4j.Log4jTest |
a | 输出日期。允许使用%d{yyyy-MM- dd HH:mm:ss}格式化日期。%d不仅支持JDKSimpleDateFormat的日期格式,还支持log4j自己的日期格式,例如ABSOLUTE,DATE,ISO8601等 | %d将输出2013-06-06 22:24:25,353 %d{yyyy-MM- dd}将输出2013-06-06 %d{ABSOLUTE}将输出22:24:25,353 %d{DATE}将输出06六月201322:24:25,253 |
F | 输出所在的类文件名称 | %F将输出Log4jTest.java |
l | 输出语句所在的行数,包括类名,方法名,文件名,行数等 | %l将输出com.log4j.test.Log4jTest.main(Log4jTest.java:50) |
L | 输出语句所在的行数,只输出数字 | %L将输出 50 |
m | 输出日志 | 输出日志,即log.info(“”),log.debug(“”)参数 |
M | 输出方法名 | %M将输出main |
n | 换行.Windows下输出\r\n,Linux下输出\n | 含行 |
p | 输出日志级别(prioriry) | DEBUG,INFO,ERROR,FITAL等 |
r | 输出从程序启动到输出该日志之间的时间间隔,单位毫秒 | %r将输出300 |
t | 输出当前的线程名称 | %t将输出main,Thread-0,Thread-1等 |
% | %%用来输出百分号 |
6、typeAliases标签—Mybatis核心文件下
用于给java类型定义别名,方便在配置文件中使用
6.1、使用方式
6.1.1、给类定义别名
<!--mybatis.xml下-->
<typeAliases> <typeAlias type="com.xxxx.pojo.User" alias="u"/>
</typeAliases>
6.1.2、 省略alias属性,表示类别名为类名,大小写不敏感
<!--mybatis.xml下-->
<typeAliases> <typeAlias type="com.xxxx.pojo.User"/> alias属性不写,默认类名,不区分大小写
</typeAliases>
6.1.3、可以通过package标签给整个包下的所有类定义别名,别名为类名
<!--mybatis.xml下-->
<typeAliases> <package name="com.xxxx.pojo"/> <!-- 包下所有的类默认类名 -->
</typeAliases>
6.2. Mybatis的内建别名
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
<!-- mapper.xml 下-->
<select id="queryAll" resultType="u"> select id,uname,upwd,birthday from t_user
</select>
<select id="queryById" resultType="User"> select id,uname,upwd,birthday from t_user where id=125
</select>
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
7、parameterType入参类型—mapper.xml
如果执行的是条件查询,DML,需要在调用方法的时候传递参数,此时, 可以在sql标签中通过parameterType属性指定参数的类型(别名|权限定名). 而在sql语句,通过#{}的方式获取参数
7.1、一个入参
<!--mapper.xml-->
<!--根据部门编号查询部门信息--><select id="queryDeptToNo" parameterType="int" resultType="Dept">SELECT DEPTNO,DNAME,LOC FROM DEPT WHERE DEPTNO = #{DEPTNO}</select>
//test.java
//selectOne("命名空间.id",入参)
Dept dept=session.selectOne("mybatis.week.mapper.DeptMapper.queryDeptToNo",10);
7.2、多个参数查询
多个参数传递时, 由于sqlSession中提供的查询方法,只允许传递一个sql参数, 因此可以对多个参数进行封装,可以对象,集合,数
<!--mapper.xml-->
<!--Javabean 根据部门编号,部门名称 来查询部门名称--><select id="queryDeptToDept" parameterType="dept" resultType="Dept">select * from dept where deptno = #{deptno} and dname= #{dname} /*占位符的名字匹配入参对象的同名属性值*/</select><!--数组 根据部门编号,来查询部门名称--><select id="queryDeptToDname" resultType="string">select dname from dept where deptno in (/*遍历集合|数组,获取到每一个数据,拼接到sql当前位置()中*/<foreach collection="array" item="item" separator=","> #{item} </foreach>)</select>
/**test.java
*/
//对象 查询30编号,sales部门的dept=session.selectOne("mybatis.week.mapper.DeptMapper2.queryDeptToDept",new Dept(30,"SALES",null));System.out.println(dept);System.out.println("___________________");//数组 查询多个部门List<String> str=session.selectList("mybatis.week.mapper.DeptMapper2.queryDeptToDname",new int[]{10,20});str.forEach(System.out::println);
7.3、入参类型
入参类型:基本数据类型|包装类 String Javabean Date 数组 List Map
7.3.1、基本数据类型|包装类
<!-- 入参类型: 基本数据类型int|Integer -->
<!-- 根据用户id查询用户信息 -->
<select id="queryById" resultType="string" parameterType="int"> SELECT * FROM emp WHERE empno = #{empno}
</select>
/* 参数基本数据类型 int->Integer
* 根据id查询用户名 第二个参数为sql传递的参数
*/
String name=session.selectOne("com.xxxx.mapper.UserMapper.queryById", 126);
System.out.println(name);
7.3.3. JavaBean
<!--Javabean 根据部门编号,部门名称 来查询部门名称-->
<select id="queryDeptToDept" parameterType="dept" resultType="Dept">select * from dept where deptno = #{deptno} and dname= #{dname} /*占位符的名字匹配入参对象的同名属性值*/</select>
//对象 查询30编号,sales部门的dept=session.selectOne("mybatis.week.mapper.DeptMapper2.queryDeptToDept",new Dept(30,"SALES",null));System.out.println(dept);
7.3.4. Map
<!--Map: 根据部门名称或者部门位置查询部门信息--><select id="queryDeptByMap" parameterType="map" resultType="Dept">select * from dept where dname = #{dname} or loc = #{loc} /*站位符的名字匹配map集合中兼职对的key值*/</select>
//MapMap<String,Object> map = new HashMap<>();map.put("dname","OPERATIONS");map.put("loc","boss办公室");List<Dept> list = session.selectList("mybatis.week.mapper.DeptMapper2.queryDeptByMap",map);list.forEach(System.out::println);
9、工具类的封装 utils
package com.xxxx.utils;
import java.io.IOException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtils {
private static SqlSessionFactory factory = null; static { try {factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml")); } catch (IOException e) { e.printStackTrace(); } }/** 返回一个会话 */ public static SqlSession getSession() { SqlSession session =null; if(factory!=null) { //session = factory.openSession();//默认手动提交事务 session = factory.openSession(true); //自动提交 }return session; }}
10、事务
- 事务是数据库操作的最小单位,有着ACID的特性,应该保证一个事务下的多条SQL语句要么都成功,要么都失败.
- Mybatis中配置了事务管理器,type属性设置JDBC,表示Mybatis采用和原生JDBC相同的事务管理机制
- 在Myabatis执行操作的开始,将自动提交功能关闭了,需要我们在执行DML操作时候,手动提交设置|设置自动提交
手动提交:
session.commit(); //事务提交
session.rollback(); //事务回滚
自动提交:
public static SqlSession getSession() { SqlSession session =null; if(factory!=null) { //session = factory.openSession(); //默认手动提交事务 session = factory.openSession(true); //自动提交 }return session;
}
11、接口绑定方案
Myabtis中,提供了一套接口绑定方案,程序员可以提供一个接口,然后提供一个与接口所对应的mapper.xml文件
Myabaits会自动讲接口与xml文件进行绑定,实际上就是Mybatis互根据接口和对应的xml文件创建一个接口的实现类,换言之,就是可以得到接口类型的一个对象,方便方法的调用
11.1、实现方式
11.1.1、定义接口
/** 接口 定义了对用户的操作 */
public interface UserMapper { //查询所有用户 public List<User> queryAll();
}
11.1.2、映射文件
注意:
- \1. xml文件名要与接口名保持一致
- \2. namespace属性值 必须与接口的权限定名
- \3. id属性必须与抽象方法名保持一致
- \4. 返回值类型和参数类型与方法的返回值和参数保持一致
<?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 ="com.xxxx.mapper.UserMapper"><!-- id 与 方法名一致 --><select id="queryAll" resultType="User"> select * from t_user </select>
</mapper>
11.1.3、在核心配置文件中扫描接口
- 扫描单个接口,可以使用mapper标签的class属性
<!-- mapper 配置扫描接口 -->
<mappers><mapper class="com.xxxx.mapper.UserMapper"/> <!--配置某个接口 --> </mappers>
2) 扫描多个接口,可以简化配置,使用package标签,表示扫描对应包下的所有接口
<!-- mapper 配置扫描接口 -->
<mappers> <package name="com.xxxx.mapper"/>
</mappers>
11.1.4、使用
在使用时,通过SqlSession的getMapper() 方法,返回接口代理对象,从而调用以实现的抽象方法
/** 测试接口绑定 */
@Test
public void test(){ SqlSession session = MybatisUtils.getSession(); //getMapper()获取接口实现类对象,参数为接口的class对象,通过参数指定接口 UserMapper mapper =session.getMapper(UserMapper.class); //通过对象调用方法 List<User> list = mapper.queryAll(); System.out.println(list); session.close();
}
- 1、通过接口绑定解决多参数传递问题
方式一
a)接口中定义方法
User selByUP(String username, String password);
b) 映射文件中提供对应的标签. 此时, SQL 语句中获取方式有两种, 通过#{arg+数字}或#{param+数字}的方式.
<select id="selByUP" resultType="user"> select * from t_user where username=#{param1} and password=#{param2} </select>
方式二
a) 接口中定义方法, 参数中使用@Param 注解设定参数名用于在 SQL 语句中使用.
User selByUP(@Param("username") String username, @Param("password") String password);
b) 映射文件中提供对应的标签. 此时, SQL 语句中获取方式有两种, 通过#{参数名称}或#{param+数字}的方式.
<select id="selByUP" resultType="user"> select * from t_user where username=#{username} and password=#{password}
</select>
11.2、接口代理开发CRUD
- 基本CRUD操作
<mapper namespace="com.xxxx.mappers.UserMapper"> <select id="queryUserByNamePwd" resultType="User"> select * from t_user where username=#{name} or userpwd = #{pwd} </select> <!-- 新增用户 --> <insert id="addUser"> INSERT INTO T_USER VALUES(seq_user_id.nextval,#{param1},#{param2}) </insert><!-- 修改用户 --> <update id="updateUser" parameterType="User"> update t_user set username=#{username},userpwd=#{userpwd} where id=#{id} </update> <!-- 删除用户 --> <delete id="deleteUser" parameterType="int"> delete from t_user where id=#{id} </delete>
</mapper>
//测试接口绑定方案crud
public interface UserMapper { //查询所有用于信息 public List<User> queryUserByNamePwd(@Param("name") String name,@Param("pwd") int pwd); //新增用户 public int addUser(String name,int pwd); //修改用户信息 public int updateUser(User user); //删除用户 public int deleteUser(int id);
}
/** 接口实现crud */
public class UserTest {
@Test
public void testDelete() {
SqlSession session = MybatisUtils.getSession(); UserMapper userMapper = session.getMapper(UserMapper.class); int rows = userMapper.deleteUser(202);if(rows>0) { System.out.println("成功"); }else { System.out.println("失败"); }session.close();
}@Test public void testUpdate() { SqlSession session = MybatisUtils.getSession(); UserMapper userMapper = session.getMapper(UserMapper.class); int rows = userMapper.updateUser(new User(201,"张三丰",1111)); if(rows>0) { System.out.println("成功"); }else { System.out.println("失败"); }session.close(); }@Test public void testInsert() { SqlSession session = MybatisUtils.getSession(); UserMapper userMapper = session.getMapper(UserMapper.class); int rows = userMapper.addUser("林更新", 45678); if(rows>0) { System.out.println("成功"); }else { System.out.println("失败"); }session.close(); }@Test public void testSelect() { SqlSession session = MybatisUtils.getSession(); UserMapper userMapper = session.getMapper(UserMapper.class); List<User> list = userMapper.queryUserByNamePwd("胡歌", 789); System.out.println(list); session.close(); }
}
11.2.3、批量操作
<mapper namespace="com.xxxx.mappers.UserMapper2"> <!-- 批量插入 --> <insert id="addUserSome" parameterType="list"> insert into tb_user(id, username, userpwd) select seq_user_id.nextval, uname, upwd from ( <foreach collection="list" item="item" separator="union" > select #{item.username} uname, #{item.userpwd} upwd from dual </foreach> ) </insert> <!-- 批量删除 --> <delete id="deleteSomeUser" parameterType="list"> delete from tb_user where id in( <foreach collection="list" item="item" separator=","> #{item} </foreach> ) </delete> <!-- 批量更新 --> <update id="updateSomeUser" parameterType="list"> <foreach collection="list" item="item" open="begin" close=";end;" separator=";">update tb_user set userpwd = #{item.userpwd} where id = #{item.id} </foreach> </update>
</mapper>
//测试批量操作
public interface UserMapper2 { //批量新增用户 public int addUserSome(List<User> user); //批量删除 public int deleteSomeUser(List<Integer> id); //批量更新 public int updateSomeUser(List<User> list);
}
public class UserTest2 { @Test public void testUpdateSome() { SqlSession session = MybatisUtils.getSession(); UserMapper2 userMapper = session.getMapper(UserMapper2.class); List<User> list = new ArrayList(); list.add(new User(218,"蓝精灵",88)); list.add(new User(219,"粉精灵",99)); list.add(new User(220,"紫精灵",00)); int rows = userMapper.updateSomeUser(list);System.out.println(rows); session.close(); }@Test public void testDeleteSome() { SqlSession session = MybatisUtils.getSession(); UserMapper2 userMapper = session.getMapper(UserMapper2.class); List<Integer> list = new ArrayList(); list.add(208); list.add(209); int rows = userMapper.deleteSomeUser(list); if(rows>0) { System.out.println("成功"); }else { System.out.println("失败"); }session.close(); }@Test public void testInsertSome() { SqlSession session = MybatisUtils.getSession(); UserMapper2 userMapper = session.getMapper(UserMapper2.class); List<User> list = new ArrayList(); list.add(new User(1,"蓝精灵",5)); list.add(new User(2,"粉精灵",6)); list.add(new User(1,"紫精灵",7)); int rows = userMapper.addUserSome(list); if(rows>0) { System.out.println("成功"); }else { System.out.println("失败"); }session.close(); }
}
12、动态SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
12.1、if
用于进行条件判断, test 属性用于指定判断条件. 为了拼接条件, 在 SQL 语句后强行添加 1=1 的恒成立条件
<select id="sel" resultType="user"> select * from t_user where 1=1 <if test="username != null and username != ''"> and username=#{username} </if><if test="password != null and password != ''"> and password=#{password} </if>
</select>
12.2、where
where ->帮助SQL语句提供where关键字如果where标签中存在条件满足,拼接where关键字如果没有条件满足,就不拼接where关键字帮助把 第一个多余的and去掉
<select id="queryIdNmToStu" resultType="Student">select <include refid="allField" /> from student /*where 1=1*/<where><if test="sno!=0 and sno!=null" >and sno=#{sno}</if><if test="sname!=null and sname!=''">and sname=#{sname}</if></where></select>
12.3、choose…when…otherwise
这是一套标签, 功能类似于 switch…case…
<select id="sel" resultType="user"> select * from t_user <where> <choose> <when test="username != null and username != ''"> and username = #{username} </when> <when test="password != null and password != ''">and password = #{password} </when> <otherwise>and 1=1 </otherwise> </choose> </where>
</select>
12.4、set
用于维护 update 语句中的 set 子句. 功能如下:
- \1. 满足条件时, 会自动添加 set 关键字
- \2. 会去除 set 子句中多余的逗号
- \3. 不满足条件时, 不会生成 set 关键字
<update id="updUser" parameterType="user"> update t_user <set>id=#{id},<!-- 防止所有条件不成立时的语法错误 --> <if test="username != null and username != ''"> username=#{username}, </if> <if test="password != null and password != ''"> password=#{password}, </if> </set> where id=#{id}
</update>
12.5、trim
用于在前后添加或删除一些内容
- \1. prefix, 在前面添加内容
- \2. prefixOverrides, 从前面去除内容
- \3. suffix, 向后面添加内容
- \4. suffixOverrides, 从后面去除内容
<update id="updUser" parameterType="user"> update t_user <!-- prefix: 前缀, 表示向前面添加内容 prefixOverrides: 从前面删除内容 suffix: 后缀, 表示向后面添加内容 suffixOverrides: 从后面删除内容 --><trim prefix="set" prefixOverrides="user" suffix="hahaha" suffixOverrides=","> username=#{username}, </trim>where id=#{id}
</update>
12.6、bind
用于对数据进行再加工, 用于模糊查询
<select id="sel" resultType="user"> select * from t_user <where> <if test="username!=null and username!=''"> <bind name="username" value="'%' + username + '%'" /> and username like #{username} </if> </where>
</select>
12.7、foreach
用于在 SQL 语句中遍历集合参数, 在 in 查询中使用
- \1. collection: 待遍历的集合
- \2. open: 设置开始符号
- \3. item: 迭代变量
- \4. separator: 项目分隔符
- \5. close: 设置结束符
List<User> selIn(@Param("list") List<Integer> list);
<select id="selIn" parameterType="list" resultType="user"> select * from t_user where id in <foreach collection="list" open="(" separator="," close=")" item="item"> #{item} </foreach> </select>
12.8、sql…include
sql用于提取 SQL 语句, include用于引用 SQL 语句
<sql id="mySql"> id, username, password </sql>
<select id="selIn" parameterType="list" resultType="user"> select <include refid="mySql" /> from t_user where id in <foreach collection="list" open="(" separator="," close=")" item="item"> #{item} </foreach> </select>
13、Mybatis缓存机制
缓存的重要性是不言而喻的。 使用缓存, 我们可以避免频繁的与数据库进行交互, 尤其是在查询越多、缓存命中率越高的情况下, 使用缓存对性能的提高更明显。
mybatis 也提供了对缓存的支持, 分为一级缓存和二级缓存。 但是在默认的情况下, 只开启一级缓存。
13.1、一级缓存
- \1. 默认开启. 线程级别的缓存, SqlSession 的缓存;
- \2. 在一个 SqlSession 生命周期中有效. SqlSession 关闭,缓存清空;
- \3. 在同一个 SqlSession 中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据;
- \4. 不同的 SqlSession 之间的缓存是相互隔离的;
- \5. 用一个 SqlSession, 可以通过配置使得在查询前清空缓存;flushCache=“true”
- \6. 任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。
13.2、二级缓存
- \1. 进程级别的缓存, SqlSessionFactory 的缓存
- \2. 在一个SqlSessionFactory生命周期中有效. 可以在多个SqlSession 生命中期中共享.
- \3. 默认关闭, 需要使用的时候, 要为某个命名空间开启二级缓存(在 mapper.xml 中配置cache).
- \4. 由于在更新时会刷新缓存, 因此需要注意使用场合:查询频率很高, 更新频率很低时使用, 即经常使用 select, 相对较少使用delete, insert, update。
- \5. 缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响。但刷新缓存是刷新整个namespace 的缓存, 也就是你 update 了一个, 则整个缓存都刷新了。
- \6. 最好在 「只有单表操作」 的表的 namespace 使用缓存, 而且对该表的操作都在这个 namespace中。 否则可能会出现数据不一致的情况
二级缓存应用场景:
对于访问多的查询请求并且用户对查询结果实时性要求不高的情况下,可采用mybatis二级缓存,降低数据库访问量,提高访问速度,如电话账单查询根据需求设置相应的flushInterval:刷新间隔时间,比如三十分钟,24小时等。。
14、关系映射
数据库中表与表之间的关系:
- 一对一 (人->身份证)
- 一对多 (夏令营->学生)
- 多对一 (学生->班级)
- 多对多 (学生->课程)
14.1、 resultMap的关联方式实现多表查询(一对一|多对一)
- \1. 在 StudentMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应班级的信息.
- \2. 通过resultMap标签定义映射关系, 并通过association标签指定对象属性的映射关系. 可以把association标签看成一个resultMap标签使用. javaType 属性表示当前对象, 可以写全限定路径或别名.
学生类中添加一个班级类型的属性 :
public class Student implements Serializable{ private int id; private String name; private int age; private String gender; private int cid; private Clazz cls;
}
StudentMapper:
<resultMap type="student" id="smap"> <id property="id" column="sid" /> <result property="name" column="sname" /> <result property="age" column="age" /> <result property="gender" column="gender" /> <result property="cid" column="cid" /> <association property="cls" javaType="clazz"> <id property="id" column="cid" /> <result property="name" column="cname" /> <result property="room" column="room" /> </association>
</resultMap> <select id="selAll" resultMap="smap"> select s.id sid, s.name sname, s.age, s.gender, c.id cid, c.name cname, c.room from t_student s left join t_class c on s.cid=c.id
</select>
14.2、resultMap的关联方式实现多表查询(一对 多)
\1. 在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应学生的信息.
\2. 通过resultMap定义映射关系, 并通过collection标签指定集合属性泛型的映射关系. 可以collection标签看成一个resultMap标签使用. ofType 属性表示集合的泛型, 可以写全限定路径或别名.
班级类中添加一个List容器存储学生类型 的数据 :
public class Clazz implements Serializable{ private int id; private String name; private int roomNum; private List<Student> stus;
}
ClazzMapper.xml:
<mapper namespace="com.xxxx.mapper.ClazzMapper"> <resultMap type="clazz" id="cmap"> <id property="id" column="cid" /> <result property="name" column="cname" /> <result property="room" column="room" /> <collection property="stus" javaType="list" ofType="student"> <id property="id" column="sid" /> <result property="name" column="sname" /> <result property="age" column="age" /> <result property="gender" column="gender" /> <result property="cid" column="cid" /> </collection> </resultMap> <select id="selAll" resultMap="cmap"> select c.id cid, c.name cname,c.room, s.id sid, s.name sname, s.age, s.gender from t_student s right join t_class c on s.cid=c.id </select>
</mapper>
14.3、列名和属性名不一致问题
如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库表的列名和类的属性名不一致时, 会导致查不到数据. 解决该问题可以
有两种方式:
1.1. 列别名
查询时, 可以通过列别名的方式将列名和属性名保持一致,继续使用自动映射, 从而解决该问题. 但是较为麻烦.
<select id="selAll" resultType="user"> select id id1, username username1, password password2 from t_user
</select>
1.2. 使用resultMap
resultMap用于自定义映射关系, 可以由程序员自主制定列名和属性名的映射关系. 一旦使用 resultMap,表示不再采用自动映射机制.
<resultMap type="user" id="umap"> <!-- id用于映射主键 --> <id column="id" property="id1" /> <!-- 非主键使用result映射 --> <result column="username" property="username1" /> <result column="password" property="password1" />
</resultMap> <select id="selAll" resultMap="umap"> select * from t_user
</select>
15、注解开发
使用注解一般用于简化配置文件. 但是, 注解有时候也不是很友好(有时候反而更麻烦), 例如动态 SQL等,所以注解和配置文件可以配合使用。
15.1、MyBatis中常用的注解
CRUD注解:
- @Select: 类似于select标签
- @Insert: 类似于insert标签
- @Update: 类似于update标签
- @Delete: 类似于delete标签
package com.xxxx.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import com.xxxx.pojo.Student;
public interface StudentMapper { @Select("select * from t_student") List<Student> selAll(); @Insert("insert into t_student values (default, #{name}, #{age}, #{gender}, #{cid})") int insStu(Student student); @Update("update t_student set age=#{1} where id=#{0}") int updStu(int id, int age);@Delete("delete from t_student where id=#{0}") int delStu(int id); }
其他注解:
- @Results: 类似于resultMap标签
- @Result: 类似<resultMap的子标签
- @One: 类似于association标签
- @Many: 类似于collection标签
public interface StudentMapper { @Select("select * from t_student") @Results( value = { @Result(column="id", property="id", id=true),@Result(column="name", property="name"), @Result(column="age", property="age"), @Result(column="gender", property="gender"),@Result(column="cid", property="cid"), @Result(property="clazz", one=@One(select="com.xxxx.mapper.ClazzMapper.selById"), column="cid") } )List<Student> sel();
}
public interface ClazzMapper { @Select("select * from t_class where id=#{0}") Clazz selById(int id);
}
16、逆向工程
mybatis-generator是一款mybatis自动代码生成工具,可以通过配置,快速生成pojo,mapper和xml文件.
官方网址:http://mybatis.org/generator/configreference/xmlconfig.html
generatorConfig.xml配置,需添加到资源包下 src下
<?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="Tables" targetRuntime="MyBatis3"> <!-- 生成的Java文件的编码 --><property name="javaFileEncoding" value="UTF-8" /> <!-- JavaBean 实现 序列化 接口 --> <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/> <commentGenerator><property name="suppressDate" value="true" /><!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="false" /></commentGenerator> <!--数据库链接地址账号密码 --><jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@localhost:1521:xe" userId="SCOTT" password="TIGER"> </jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true 时把 JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --><javaTypeResolver><property name="forceBigDecimals" value="false" /> </javaTypeResolver><!--生成 Model 类存放位置 --> <javaModelGenerator targetPackage="com.xxxx.pojo" targetProject="mybatis12\src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!--生成映射文件存放位置 --> <sqlMapGenerator targetPackage="com.xxxx.mappers" targetProject="mybatis12\src"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!--生成接口类存放位置(Dao|Mapper) --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.xxxx.mappers" targetProject="mybatis12\src"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 参考数据库中需要生成的对应表信息 --> <table tableName="dept" domainObjectName="Dept" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="emp" domainObjectName="Emp" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context>
</generatorConfiguration>
Java SE MyBatis框架(详解)相关推荐
- 干货必看|Spring Boot整合MyBatis框架详解
在开发中,我们通常会对数据库的数据进行操作,Sprirng Boot对关系型数据库和非关系型数据库的访问操作都提供了非常好的整合支持.所以今天壹哥就给大家讲解一下,如何在SpringBoot环境中整合 ...
- mybatis框架详解
一.简介 1.历史 mybatis的前身是apache ibatis,2010年由ASF转移到google code,从ibatis3.x改名为mybatis,2013年转移到github.mybat ...
- Java并发——Executor框架详解(Executor框架结构与框架成员)
一.什么是Executor框架? 我们知道线程池就是线程的集合,线程池集中管理线程,以实现线程的重用,降低资源消耗,提高响应速度等.线程用于执行异步任务,单个的线程既是工作单元也是执行机制,从JDK1 ...
- Java SE基础知识详解第[12]期—集合(Set、Collections、Map、集合嵌套)
写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...
- Java SE基础知识详解第[13]期—不可变集合、Stream流、异常
写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...
- Java SE基础知识详解第[18]期—网络编程(通信)
写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...
- java编译器源码详解_已更新至第8章 | LLVM 编译框架详解
LLVM是什么? 我又不做编译器研究,干嘛要管它? 这是一些朋友想要对LLVM发起的提问,那么今天我们就来看看那款据说很酷炫的编译器--LLVM. LLVM是什么? LLVM是一个自由软件项目,它是一 ...
- Java 集合框架 详解
一.Java 集合框架概述 集合框架是一个用来代表和操纵集合的统一架构(java集合框架位于java.util包中).所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.例如 Collec ...
- springboot2整合mysql5_SpringBoot2整合SSM框架详解
SpringBoot2整合SSM框架详解 发布时间:2019-01-15 21:33, 浏览次数:1218 , 标签: SpringBoot SSM <>开发环境 * 开发工具:Eclip ...
最新文章
- 当统计信息不准确时,CBO可能产生错误的执行计划,并在10053 trace中找到CBO出错的位置示例...
- PHP遇到json解决的两个办法,转为数组,直接取值
- 阿里云CentOS7安装Oracle11GR2
- python open encoding为无效的参数_TypeError:“encoding”是无效的关键字参数ex23.py
- android 手机自动化测试,Appium进行Android手机真机自动化测试
- 让你的silverlight更炫(一):从自定义控件说起
- docker删除所有容器和镜像
- python棋盘覆盖_java实现的棋盘覆盖
- mina框架详解(一)
- Wagtail 教程 1 :基础设置
- Mac中隐藏/显示文件或文件夹
- v3S移植mplayer播放器
- 三星Q990B全景声回音壁评测
- 如何计算图论中的模块化modularity指标,图论中的社区检测算法——Louvain community
- SpringBoot整合Shiro学习(上)
- oracle 的lag,LAG函数的使用
- 手把手写C++服务器(7):给C语言程序员看的C++科普
- 电视信号网络直播方案
- matlab访问脉冲传递函数的分母,笔记:系统模型转换
- 直饮水机按键板触摸弹簧过于灵敏问题