MyBatis 简介
6.1 发展: 原为apache项目IBatis项目,2010年迁移到Google Code 并更名为MyBatis,2013迁移到GitHub.
6.2 作用: 持久层框架.
6.3 解释: 半自动化ORM(Object Relational Mapping)框架
6.3.1ORM: 对象/关系 映射
6.3.1.1对象:面向对象编程语言(实体类对象)
6.3.1.2关系:关系型数据库
6.3.1.3作用:解决编程语言和数据库发展不一致问题.是面向对象编程语言和关系型数据库之间的桥梁
6.3.1.4使用ORM时只需要把对象传递给ORM,剩下的拆分对象等事情全由ORM完成,并把对象中内容传递给数据库.
6.3.2半自动:把对象传递给ORM之后,还需要编写SQL命令.
6.3.2.1使用MyBatis框架后没有XXXDaoImpl类了,但是需要编写SQL,把实现类替换成XML文件,文件中编写SQL命令.
7. MyBatis 环境搭建
7.1 导入jar包
7.2 编写MyBatis全局配置文件.主要放置4个变量.在src下新建任意名称的xml文件
7.2.1没有提示,引入dtd的步骤
7.2.1.1在源码文件夹中搜索mybatis-3-config.dtd
7.2.1.2把文件复制到任意没有中文的目录下
7.2.1.3复制http://mybatis.org/dtd/mybatis-3-config.dtd
7.2.1.4eclipse菜单windowà preferencesà XMLàxmlcatalogàadd按钮
7.2.1.4.1location:浏览粘贴dtd
7.2.1.4.2key type:system id
7.2.1.4.3key中粘贴7.2.1.3 复制那句话
7.2.1.5关闭xml文件或重启eclipse
<?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> <!-- default引用下面environment,引用谁,当前使用哪个环境 --> <environments default="demo"> <environment id="demo"> <!-- 与JDBC事务管理相同 --> <transactionManager type="JDBC"></transactionManager> <!-- 使用数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="smallming"/> </dataSource> </environment> </environments> <mappers> <!-- 文件夹 --> <mapper resource="com/bjsxt/mapper/FlowerMapper.xml"/> </mappers> </configuration>
|
7.3 在mapper包下创建:实体类Mapper.xml的映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- 理解成类的全限定路径:包名+类名 --> <mapper namespace="com.bjsxt.mapper.FlowerMapper"> <!-- id:方法名 resultType:返回值类型 如果返回值为集合,返回值类型写集合的泛型类型 parameterType:参数类型 --> <select id="selAll" resultType="com.bjsxt.pojo.Flower"> select * from flower </select> </mapper> |
7.4 编写测试代码
InputStream is = Resources.getResourceAsStream("mybatis.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); SqlSession session = factory.openSession(); List<Flower> list = session.selectList("com.bjsxt.mapper.FlowerMapper.selAll"); for (Flower flower : list) { System.out.println(flower.toString()); } session.close(); |
8. 搭建详解
8.1 jar介绍
8.2 全局配置文件mybatis.xml
8.2.1<environments default="demo">
8.2.1.1default配置当前所使用的环境.值必须是<environment>的id值
8.2.1.2可以有多个<environment>子标签.
8.2.2<environment> 声明可能使用的环境,会被< environments>
8.2.3<transactionManager type="JDBC">
8.2.3.1事务管理器类型.
8.2.3.2type属性可取值:
8.2.3.2.1JDBC 底层事务与JDBC原有事务相同
8.2.3.2.2MANAGED MyBatis不去管理事务,交给其他框架进行管理.
8.2.4<dataSource type="POOLED">
8.2.4.1POOLED : 使用连接池技术. 访问频率比较高时使用连接池结束,可以降低数据库压力.
8.2.4.2UNPOOLED: 不使用连接池技术.每次对数据库访问时打开数据库连接,访问结束后关闭数据库连接.
8.2.4.3JNDI : java命名目录接口.数据库的连接可以依赖于其他技术或应用.
8.2.5<mapper> 常用属性
8.2.5.1resource=”com/bjsxt/xxx.xml” 加载项目中资源,目录寻找,中间是/
8.2.5.2url=”” 加载互联网或本机任意目录的配置文件.
<mapper url="file:///E:/FlowerMapper.xml"/> |
8.3 mapper.xml 中标签解释
8.3.1<mapper >中namespace=””值相当于接口名
8.3.2id 属性: 相当于方法名
8.3.3resultType属性:返回值类型,如果返回值是集合,写集合的泛型.
8.3.4parameterType属性:参数类型.如果没有参数省略该属性.
<select id="selAll" resultType="com.bjsxt.pojo.Flower" parameterType=""> select * from flower </select> |
8.4 测试代码:
8.4.1为什么使用SqlSessionFactoryBuilder
8.4.1.1构建者设计模式:方便/快速帮助对某个类或接口进行实例化.
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); |
8.4.2根据工厂产生SqlSession对象
8.4.2.1MyBatis把所有对数据库执行CRUD的API放入到了SqlSession中
SqlSession session = factory.openSession(); |
8.4.3释放资源,事务回滚.如果需要进行事务提交必须在编写:session.commit();
session.close(); |
9. MyBatis实现查询及参数获取
9.1session的常用查询方法
9.1.1 session.selectList(“查询标签的id值的完整路径”);
9.1.1.1泛型的类型与resultType属性的类型相同.
9.1.1.2如果resultType=”com.bjsxt.pojo.Flower”时,selectList方法返回值List<Flower>
9.1.1.如果resultType=”map”时,selectList方法返回值为List<Map<String,Object>> 其中列名自动成为Map的key
9.1.2session.selectMap(“查询标签的id值的完整路径”,”列名:哪个列当作Map的key”),只适用于希望通过某一列快速找到这一行
9.1.2.1resultType影响Map的value
9.1.2.2如果resultType=”com.bjsxt.pojo.Flower”时,selectMap方法返回值Map<String,Flower>
9.1.2.3如果resultType=”map”时,selectMap方法返回值Map<String,Map<String,Object>>
Map<Object, Object> map = session.selectMap("com.bjsxt.mapper.FlowerMapper.selAll", "name"); |
9.1.3session.selectOne(“查询标签的id值的完整路径”)
9.1.3.1要求查询结果必须只能有一个或没有查询结果
9.2paramterType属性,设置方法参数.
9.2.1如果参数是基本数据类型或String需要通过#{从0开始的索引}或#{param1}
9.2.1.1如果参数只有一个,#{内容随意写}
9.2.1.2通过selectOne()或selectList()或selectMap()第二个参数传递方法参数,参数只能有一个(可以写多个,另一种写法,明天讲)
<select id="selById" resultType="com.bjsxt.pojo.Flower" parameterType="int"> select * from flower where id=#{alksdjfalasdfasdf} </select> |
Flower flower = session.selectOne("com.bjsxt.mapper.FlowerMapper.selById",3); |
9.2.2如果参数类型对象类型时,使用#{属性名}获取对象的属性
<select id="selByNameProduction" resultType="com.bjsxt.pojo.Flower" parameterType="com.bjsxt.pojo.Flower"> select * from flower where name like #{name} and production like #{production} </select> |
9.2.3如果参数类型是Map时,使用#{key}取出对应的value
<select id="selByName" resultType="com.bjsxt.pojo.Flower" parameterType="map"> select * from flower where name like #{abc} </select> |
Map<String,Object> map = new HashMap<>(); map.put("abcd", "%百%"); List<Flower> list = session.selectList("com.bjsxt.mapper.FlowerMapper.selByName", map); System.out.println(list); |
10. MyBatis实现新增
10.1新增,删除,修改标签都没有resultType,因为返回值一定是int类型
10.2增加删除修改都需要提交事务.
10.2.1通过session.commit();提交事务.
10.2.2通过开启session自动提交功能,在openSession(true);不需要写sessin.commit();不推荐,因为session对象可能执行的是查询,不需要提交事务.
SqlSession session = factory.openSession(true); |
10.3实现步骤
10.3.1在mapper.xml中配置<Insert>
<insert id="insFlower" parameterType="com.bjsxt.pojo.Flower"> insert into flower values(default,#{name},#{price},#{production}) </insert> |
10.3.2测试代码
Flower flower = new Flower(); flower.setName("测试222"); int index = session.insert("com.bjsxt.mapper.FlowerMapper.insFlower", flower); System.out.println(index); |
11. MyBatis 实现修改
11.1需要提交事务
11.2步骤
11.2.1在mapper.xml配置<update>
<update id="updFlower" parameterType="com.bjsxt.pojo.Flower" > update flower set name=#{name} where id=#{id} </update> |
11.2.2测试代码
Flower flower = new Flower(); flower.setId(2); flower.setName("测试222");
int index = session.update("com.bjsxt.mapper.FlowerMapper.updFlower", flower); System.out.println(index); |
12. MyBatis实现删除
12.1 不要忘了提交事务
12.2 实现步骤
12.2.1mapper.xml配置<delete>标签
<delete id="delById" parameterType="int"> delete from flower where id = #{0} </delete> |
12.2.2测试代码
int index = session.delete("com.bjsxt.mapper.FlowerMapper.delById", 2); System.out.println(index); |
1) MyBatis全局配置文件讲解
1.<properties>标签使用
a) 可以加载外部文件.例如在src下创建db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root |
b) 可以在XML中自定义属性值
<properties resource="db.properties"> <property name="jdbc.password" value="smallming" /> </properties> |
c) 通过${key}取出属性值
<environments default="demo"> <environment id="demo"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments> |
d) 好处:改变数据时,更加精确的知道去哪里修改
2. <typeAliases>起别名
a) 给某个类起别名
<typeAliases> <typeAlias type="com.bjsxt.pojo.Flower" alias="abc"/> </typeAliases> |
b) 给某个包下所有类起别名,这些类的别名为类名
<typeAliases> <package name="com.bjsxt.pojo"/> </typeAliases> |
c) 系统内置别名:封装类的别名都是对应关键字.关键字的别名都是在前面_,所有别名都是小写
3.<settings>标签
a) 整个mybatis全局开关.
b) 举例:设置开启MyBatis对log4j的支持
i. LogImpl 没有默认值,默认不开启Log4j功能
<settings> <setting name="logImpl" value="LOG4J"/> </settings> |
2) Log4J
1. Log4J是专门为java语言编写的日志打印的类库
2. 使用步骤:
a) 把log4j导入到项目中
b) 并在src下新建log4j.properties 属性文件,配置log4j
3. Log4j: 常用在异常记录上,可以把信息打印在控制台上或打印到文件中
4. Log4J的五种级别:
a) Fatal 严重错误
b) Error 错误
c) Warn 警告
d) Info 普通信息
e) Debug 调试信息
5. 优先级: fatal> error> warn >info > debug
6. 使用时编写代码
Logger logger = Logger.getLogger(FlowerServiceImpl.class); logger.debug("调试信息"); logger.info("普通信息"); try { int i = 5+2; } catch (Exception e) { // e.printStackTrace(); logger.error(e.getMessage()); } |
3) MyBatis对日志的支持
1. 需要在mybatis.xml中开启对log4j的支持
<settings> <setting name="logImpl" value="LOG4J"/> </settings> |
2. 保证有log4j1.xxxx.jar
3. 在src下放置log4j.properties文件.
# Set root category priority to INFO and its only appender to CONSOLE. log4j.rootCategory=ERROR, CONSOLE #log4j.rootCategory=INFO, CONSOLE, LOGFILE log4j.logger.com.bjsxt.mapper=debug # 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= %C %m %n # LOGFILE is set to be a File appender using a PatternLayout. log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=E:/demo.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%m %l %n |
4. MyBatis输出级别
a) 命名级别(包级别)log4j.logger.com.bjsxt.mapper,表示命名空间(namespace)以这个开头日志就会被打印
b) 接口级别:log4j.logger.com.bjsxt.mapper.FlowerMapper,该命名空间(接口)所有的方法日志都被打印
c) 方法级别:log4j.logger.com.bjsxt.mapper.FlowerMapper.selAll,只有这个方法的日志被打印
5. MyBatis中${}和#{}的区别
a) #{}使用?占位符
b) ${}直接进行字符串拼接
3)接口绑定及多参数处理
1. 实现步骤
A) 在mybatis.xml中设置<mappers>子标签<package>扫描mapper包
<mappers> <package name="com.bjsxt.mapper"/> </mappers> |
B) 在mapper包创建接口名和xml文件名相同.
C)接口的全限定路径(包名+类名)和xml文件的namespace相同.
D)接口中方法和xml中标签的id相同
2. 好处:
a) 与正常编写代码习惯相同.
b) 支持多参数
4) 动态SQL
1. 动态SQL:根据不同的参数形成不同的SQL命令
2. MyBatis中为什么单独有动态SQL支持?
a) MyBatis不需要编写实现类,以前写到方法中的逻辑判断代码不能编写.在mapper.xml中添加一些标签,实现与之前逻辑判断相同效果
3. <if>的使用
a) 逻辑判断,test属性中内容本质OGNL表达式.
i. 如果参数是对象属性直接写属性名
ii. 如果参数是多个基本数据类型或String写parma1,param2
<select id="selByNamePro" resultType="Flower"> select * from flower where 1=1 <if test="param1 !=null and param1!=''"> and name=#{param1} </if> <if test="param2!=null and param2!=''"> and production=#{param2} </if> </select> |
Iii. 使用注解给参数设置名称.MyBatis把参数转换为Map集合,在mapper.xml中通过key取出Map中内容. 其中key是注解中起的名
List<Flower> selByNamePro(@Param("name") String name ,@Param("production") String production); |
<select id="selByNamePro" resultType="Flower"> select * from flower where 1=1 <if test="name !=null and name!=''"> and name=#{name} </if> <if test="production!=null and production!=''"> and production=#{production} </if> </select> |
4. <where>标签
a) 帮助生成where关键字,并自动帮助去掉第一个and.如果<where>中最终没有内容,不生成where关键字
<select id="selByNamePro" resultType="Flower"> select * from flower <where> <if test="name !=null and name!=''"> and name=#{name} </if> <if test="production!=null and production!=''"> and production=#{production} </if> </where> </select> |
5. <choose>相当于if...else if....或swtch中没有case块都有break;
a) 示例代码.只有最多有一个分支执行
<select id="selByNamePro" resultType="Flower"> select * from flower where 1=1 <choose> <when test="production!=null and production!=''"> and production=#{production} </when> <when test="name !=null and name!=''"> and name=#{name} </when> <otherwise> and 2=2 </otherwise> </choose> </select> |
6. <foreach> 循环迭代,常与in查询结合使用
a) Collection: 要遍历的集合对象
b) Open: 最前面添加的内容
c) Close: 最后面添加的内容
d) Separeator:分隔符
e) Item:迭代变量
<select id="foreach" parameterType="list" resultType="Flower"> select * from flower where id in <foreach collection="list" open="(" close=")" separator="," item="myitem"> #{myitem} </foreach> </select> |
7. <set> 生成update语句中set关键字,并自动去掉最后一个逗号
<update id="set" parameterType="Flower"> update flower <set> <if test="name!=null and name!=''"> name=#{name}, </if> <if test="production!=null and production!=''"> production=#{production}, </if> </set> where id=#{id} </update> |
8. <trim> 实现在最前面添加内容或去除最前某个内容或在最后面添加内容或去除最后面的某个内容
a) <trim>能实现<where>和<set>完全相同的效果
<update id="set" parameterType="Flower"> update flower <trim prefix="set" suffixOverrides="" > <if test="name!=null and name!=''"> name=#{name}, </if> <if test="production!=null and production!=''"> production=#{production}, </if> </trim> where id=#{id} </update> |
9.<bind>绑定,给参数重新赋值
a) 多用在模糊查询中.
b) <bind>的value属性%两次添加单引号,认为%是字符串.name是变量,一定不要添加’’
<select id="bind" parameterType="Flower" resultType="Flower"> <bind name="name" value="'%'+name+'%'"/> select * from flower where name like #{name} </select> |
10. <include>和<sql>
a) <include>和<sql>结合使用
b) <sql>定义出一些比较难写且常用的sql片段,通过<include>引用内容,达到复用效果
<select id="sql" resultType="Flower"> select <include refid="mysql"/> from flower </select> <sql id="mysql"> id,name,price,production 假设有80列 </sql> |
11. <selectKey> 根据设定的规则生成主键内容,常用在新增
a) KeyProperty:把结果设置到哪个属性中
b) Order可取值BEFORE|AFTER,表示在SQL语句之前执行活之后执行
c) ResultType表示<selectKey>里面sql语句最终结果类型
<insert id="selectKey" parameterType="Flower"> <selectKey keyProperty="id" order="BEFORE" resultType="int"> select max(id)+3 from flower </selectKey> insert into flower values(#{id},#{name},#{price},#{production}) </insert> |
5)MyBatis 缓存
1. 为什么有缓存?
a) 应用中相对比较耗时的操作就是与数据库交互的过程.每次提成程序执行效率第一反映减少与数据库交互过程
b) 缓存:在与数据库交互之间添加中间件.这个中间件就是缓存.如果缓存中已经有需要的数据直接从缓存中取,如果没有才去访问数据库
2. 缓存好处
a) 提升程序执行效率.减少与数据库的交互
3. MyBatis中缓存分类
a) SqlSession缓存
b) SqlSessionFactory缓存
4. SqlSession缓存
a) 有效范围同一个SqlSession对象
b) 缓存以标签最为缓存基本单位.(调用某个查询<select>之后,把查询的结果缓存)
c) 默认SqlSession缓存开启
5. SqlSessionFactory缓存
a) 有效范围SqlSessionFactory对象
b) 默认不开启.
c) 在需要被缓存的mapper.xml中添加
i. 如果没有readOnly=”true”需要把实体类序列化
<cache readOnly="true"></cache> |
d) 只有当SqlSession对象关闭(session.close())或提交时(session.commit())才会把SqlSession缓存的内容复制到SqlSessionFactory中
e) 缺点:
开启SqlSessionFactory缓存后可能出现
1. 影响程序执行效率
2. 出现违法数据
6) ThreadLocal
1. JDK中的类.
2. ThreadLocal是一个容器,里面能存储一个Object对象.
3. 只要线程不改变,这个对象可以在任意位置被操作.
4. 测试代码
final ThreadLocal<String> tl =new ThreadLocal<>(); // tl.set("abc");
new Thread(){ public void run() { tl.set("abc"); System.out.println("子线程中取:"+tl.get()); }; }.start();
System.out.println("外部:"+tl.get()); |
一. Auto Mapping 使用
1. MyBatis 自动映射功能.在查询时只要保证列名和属性名相同,可以把查询结果自动填充到属性中
2. 如果出现列名和实体类属性名不相同时,可以在查询语句中给列起别名
二.<resultMap>
1. 通过<resultMap>手动指定列和属性之间的关系
2. 示例代码
<resultMap type="Classroom" id="mymap"> <id column="id" property="id"/> <result column="name" property="cname"/> </resultMap>
<select id="selAll1" resultMap="mymap"> select * from classroom </select> |
三.多表查询-业务装配方式
1. 给定数据库设计
create table classroom( id int(10) primary key auto_increment, name varchar(20) ); |
create table student( id int(10) primary key auto_increment, name varchar(20) not null, cid int(10) REFERENCES classroom(id) ); |
2. 实体类设计
2.1 为什么需要在Student中添加Classroom对象?
2.1.1 因为需要在查询Student时候同时需要使用CLassroom中内容,如果不把Classroom放入到Student中,需要传递给别人两个对象.而现在,只需要把Student传递给别人即可.
public class Classroom { private int id; private String name; |
public class Student { private int id; private String name; private int cid; private Classroom classroom; |
3. 实现代码
3.1 使用业务装配功能(使用java代码,执行多个查询,把查询结果通过set方法设置都一个对象中)
List<Student> listStudent = session.selectList("a.c.selAll"); for (Student student : listStudent) { student.setClassroom((Classroom)session.selectOne("a.b.selById",student.getCid())); System.out.println(student.toString()+"班级:"+student.getClassroom().getName()); } |
四.多表查询-<resultMap>方式自动查询关联的一个对象
1. 需要在MyBatis的mapper.xml中进行配置,达到查询学生时可以把对应的班级查询出来
2. 实现关联一个对象时步骤:
2.1 表设计和实体类设计与多表查询-业务装配方式一样
2.2 mapper.xml设置配置,设定查询Student是同时查询出Classroom
2.2.1 在ClassroomMapper.xml中有
<select id="selById" resultType="Classroom" parameterType="int"> select * from classroom where id=#{0} </select> |
2.2.2 在StudentMapper.xml中
2.2.2.1 <association> 查询所关联的对象(单位:一个)
2.2.2.2 property属性: 另一个类在当前类中属性名
2.2.2.3 select属性:调用哪个查询.这个查询在哪个mapper.xml中都可以被调用
2.2.2.4 column属性:把当前查询的哪个列作为参数传递给另一个查询
<resultMap type="Student" id="myresultmap"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="cid" property="cid"/> <!-- 在最终返回Student对象时,同时帮助去查询以下所关联的对象 --> <association property="classroom" select="a.b.selById" column="cid"></association> </resultMap> <select id="selAll" resultMap="myresultmap"> select * from student </select> |
五.多表查询-<resultMap>方式自动查询关联的集合对象
1. 表设计与上面相同
2. 实体类
public class Student { private int id; private String name; private int cid; private Classroom classroom;//写不写都可以 |
public class Classroom { private int id; private String name; private List<Student> list; |
3. 在StudentMapper.xml中添加通过cid查询
<select id="selByCid" resultType="Student" parameterType="int"> select * from student where cid=#{0} </select> |
4. 在ClassroomMapper.xml中添加查询全部
<resultMap type="Classroom" id="myresultmap1"> <id column="id" property="id"/> <result column="name" property="name"/> <collection property="list" select="a.c.selByCid" column="id" ></collection> </resultMap> <select id="selAll3" resultMap="myresultmap1"> select * from classroom </select> |
六. 从三到五这几种多表查询方式都叫做N+1次查询
1. 假设学生中有3条数据,对应3个班级.查询学生时同时把所关联的班级查询出来,这个执行过程设计到了几条查询?
1. Select *from student
2. Select *from classroom where id=?
3. Select *from classroom where id=?
4. Select *from classroom where id=?
2. N+1 其实就是查询哪个表,如果这个表有N条数据,需要执行N+1次查询才能把这个表中数据和关联对象的数据查询出来.
3. 缺点:
3.1 查询SQL命令执行次数过多.导致效率降低.
4. 解决办法:
4.1 添加缓存.在项目执行最开始,查询全部.放入缓存中,以后每次执行都是从缓存中读取
4.2 把N+1次查询替换成外连接查询
七. 多表查询-外连接-<resultMap>方式
1. 只适用于查询外键表时同时查询主键表对象
2. 实现步骤:mapper.xml中有变化
<resultMap type="Student" id="mymap"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="cid" property="cid"/> <association property="classroom" javaType="Classroom"> <id column="cid" property="id"/> <result column="cname" property="name"/> </association> </resultMap> <select id="selAll" resultMap="mymap"> select s.id,s.name,s.cid,c.id cid,c.name cname from student s left join classroom c on s.cid=c.id </select> |
八. 多表查询-外连接-AutoMapping方式
1. 把关联的对象中属性通过起别名,别名格式: `对象名.属性名` 其中`是mysql中去关键字的.点在sql命令是关键字
2. 实现方式
<select id="selAll1" resultType="Student"> select s.id,s.name,s.cid,c.id `classroom.id`,c.name `classroom.name` from student s left join classroom c on s.cid=c.id </select> |
九. 注解
1. 任何框架注解和配置文件都可以结合使用
2. 使用注解时mybatis.xml中设置<mappers>中
<mappers> <mapper class="com.bjsxt.mapper.ClassroomMapper" /> <mapper class="com.bjsxt.mapper.StudentMapper" /> </mappers> |
3. 查询
@Select("select * from classroom where id = #{0}") Classroom selById(int id); |
4. 删除
@Delete("delete from classroom where id = #{0}") int delById(int id); |
5. 新增
@Insert("insert into classroom values(default,#{name})") int insCLassroom(Classroom c); |
6. 修改
@Update("update classroom set name=#{name} where id=#{id}") int updClassroom(Classroom room); |
7. @Results实现多表查询的三种方式
7.1 应用AutoMapping,起别名
@Select("select s.id,s.name,s.cid,c.id `classroom.id`,c.name `classroom.name` from student s left join classroom c on s.cid=c.id") List<Student> selAll(); |
7.2 使用@Results结合外连接
//如果注解中某个属性是xxx[],其中xxx如果是基本数据类型或string写成 value={x,x,x} //如果xxx是引用数据类型value={@xxx()} //如果这个属性只取一个值,可以省略{} @Results(value={ @Result(column="id",property="id",id=true), @Result(column="name",property="name"), @Result(column="cid",property="cid"), @Result(property="classroom.id",column="cid2"), @Result(column="cname",property="classroom.name") }) @Select("select s.id,s.name,s.cid,c.id cid2,c.name cname from student s left join classroom c on s.cid=c.id") List<Student> selAll1(); |
7.3 使用@Results结合N+1方式
7.3.1 @One() 查询当前类中一个对象,对象的数据来源与另一个查询
7.3.2 @Many() 查询当前类中一个集合对象,对象的数据来源于另一个查询
@Select("select * from classroom where id = #{0}") Classroom selById(int id); |
@Results(value={ @Result(column="id",property="id",id=true), @Result(column="name",property="name"), @Result(column="cid",property="cid"), @Result(property="classroom",one=@One(select="com.bjsxt.mapper.ClassroomMapper.selById"),column="cid") }) @Select("select * from student") List<Student> selAll2(); |
十. MyBatis运行原理
1.所有涉及的类
1.1ClassLoaderWrapper:负责去加载全局配置文件的类,转换为流或URL等
1.2.XMLConfigBuilder:负责把全局配置文件流解析成Configuration
1.3.Configuration:存储MyBatis.xml解析后的内容
1.4.DefaultSqlSessionFactory:SqlSessionFactory接口的实现类
1.5.Transaction:MyBatis中事务类.一个SqlSession只对应一个事务对象
1.6.DefaultSqlSession是SqlSession接口的实现类
1.7.getMapper()底层使用JDK中Proxy创建接口的动态代理对象
1.8.Executor 执行器
2. 执行流程图
3. 文字解释
从MyBatis开始运行时会使用ClassLoaderWrapper把全局配置文件和mapper文件和接口转换为流并传递给XMLConfigBuilder进行解析parser,解析完成后会产生Configuration并把Configuration对象传递给SqlSessionFactory接口实现类DefaultSqlSessionFactory进行实例化SqlSessionFactory.
使用SqlSession工厂SqlSessionFactory频繁生产SqlSession接口实现类DefaultSqlSession类对象.每次生产SqlSession对象时会产生唯一Transaction事务对象.
之后会产生所使用接口的动态代理对象,使用代理对象调用接口中方法.调用接口方法本质调用xml中标签.
当事务实现完成后可能需要提交事务.如果事务commit失败,需要rollback
最后需要关闭SqlSession释放资源.
以上就是MyBatis详细运行原理(这句话是给面试官说的)
十一. 分页
1. MySql中分页SQL命令
1.1 limit第一个参数表示从0开始索引,从哪条开始显示.
1.2 limit第二个参数表示显示几个
select * from classroom limit 3,2 |
2. Mybatis中编写分页
2.1 示例
@Select("select * from classroom limit #{0},#{1}") List<Classroom> selByPage(int pageStart,int pageSize); |