Mybatis全解
Posted Recently 祝祝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis全解相关的知识,希望对你有一定的参考价值。
什么是Mybatis:
mybati是一个半自动化轻量级持久性框架,支持自定义SQL、存储过程和高级映射。MyBatis消除了几乎所有的JDBC代码以及手动设置参数和检索结果。MyBatis可以使用简单的XML或注释进行配置,并将原语、接口和Java POJO(普通的旧Java对象)映射到数据库记录
什么是半自动化轻量级持久性框架:
**半自动化:**手动实现SQL
**轻量级:**运行效率比较高(事实测试)
**持久化:**数据持久化(Mybatis,hibernate,jpa)
Mybatis底层原理—》动态代理:
通过动态代理产生会话,运行mybatis相关配置
package com.uplooking.utils;
import java.io.InputStream;
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 {
// 接在配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis.cfg.xml");
factory = new SqlSessionFactoryBuilder().build(inputStream);
System.out.println(factory);
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
return factory.openSession(false);
}
public static void closeSqlSession(SqlSession sqlSession) {
if (sqlSession != null) {
sqlSession.close();
}
}
}
关键语句:
先是用Resources.getResourceAsStream读取配置文件返回一个字节流类型的数,
在创建一个 SqlSessionFactory对象,通过new SqlSessionFactoryBuilder().build(inputStream)导入刚刚读取到的字节流获得
在通过得到的会话工厂开启会话,默认为FALSE,factory.openSession(false);
之后就可以使用了,只需要在执行类里通过建造代理类,使用代理类调用getMapper方法,传入对象就能产生一个代理了
Mybatis使用:
只需要在java项目下面建立一个lib文件夹将Mybatisjar包导入即可使用,如果需要连接数据库还需要导入JDBC相关的包
这是我导入的包:
Mybatis基本配置:
mybatis核心配置文件:
<?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>
<!--mybatis SQL脚本跟踪-->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!--启动二级缓存 默认为false-->
<setting name="cacheEnabled" value="true" />
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mytest"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mappers/DeptDO.xml"/>
<mapper resource="mappers/EmpDO.xml"/>
</mappers>
</configuration>
相关对象的配置文件:
接口方法返回一对多,就是链表查询,返回一个链表类型:
<mapper namespace="绑定的接口全类名">
<resultMap type="Bean对象全类名" id="规则名">
<result column="id" property="id"/>
<result column="dept_name" property="dname"/>
...
<collection property="List属性名" ofType="List里的类的全类名">
<id column="数据库主键名" property="List里的类的属性名"/>
<result column="数据库列名" property="List里的类的属性名"/>
</collection>
</resultMap>
</mapper>
重点句:<collection property="List属性名" ofType="List里的类的全类名">
接口方法返回值多对一 ,返回值为单个类型:
<mapper namespace="绑定的接口全类名">
<resultMap type="Bean对象全类名" id="Bean对象全类名">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
...
<association property="自定义类属性名" select="接口全类名.方法名(即其它sql配置文件的语句)"
column="列名(即传入查到的哪一列作为其它sql语句需要传入的参数值)">
</association>
</resultMap>
</mapper>
重点语句:
<association property="自定义类属性名" select="接口全类名.方法名(即其它sql配置文件的语句)"
column="列名(即传入查到的哪一列作为其它sql语句需要传入的参数值)">
</association>
只是改变查询列的属性名与数据库属性名不同,只需要更改映射表返回值类型变为自定义类型即可:
<mapper namespace="绑定的接口全类名">
<resultMap type="Bean对象全类名" id="规则名">
<id column="数据库下的主键名" property="Bean对象的属性名"/>
<result column="数据库下的列名" property="Bean对象的属性名"/>
</resultMap>
<select id="接口方法" resultMap="规则名">
.....
</select>
</mapper>
批量插入:
接口:
配置文件:
<insert id="insertBatch">
insert into deptbl(deptno,dname,loc) values
<foreach collection="items" item="item" separator=",">
(#{item.deptno},#{item.dname},#{item.loc})
</foreach>
</insert>
重点语句:
<foreach collection="items" item="item" separator=",">
测试:
批量删除:
配置文件:
<delete id="deleteBatch">
delete from deptbl where deptno in
<foreach collection="ids" open="(" separator="," close=")" item="id">
${id}
</foreach>
</delete>
重点代码:
<foreach collection="ids" open="(" separator="," close=")" item="id">
测试:
条件查询:
分页:
<!-- 分页 -->
<select id="find5" resultType="com.uplooking.pojo.EmpVO">
select empno,ename,sal,deptno FROM emp
<if test="cond.sal!=null ">
order by ${cond.sal}
</if>
<if test="cond.order!=null and cond.order!=''">
${cond.order}
</if>
limit #{limit},#{size}
</select>
排序:
<!-- 排序查询 -->
<select id="find4" resultType="com.uplooking.pojo.EmpVO" >
SELECT empno,ename,sal,deptno FROM emp
<if test="cond.sal!=null ">
order by ${cond.sal}
</if>
<if test="cond.order!=null and cond.order!=''">
${cond.order}
</if>
模糊查询:
<select id="find3" resultType="com.uplooking.pojo.EmpVO" >
SELECT empno,ename,sal,deptno FROM emp
<where>
<if test="cond.name!=null and cond.name!=''">
ename like concat('%',#{cond.name},'%')
</if>
<if test="cond.job=null and cond.job!=''">
AND JOB=#{cond.job}
</if>
<if test="cond.sal!=null and cond.sal!=''">
AND sal < =#{cond.sal}
</if>
</where>
</select>
重点语句:
ename like concat('%',#{cond.name},'%')
细节-> 处理自增列
selectKey 会将 SELECT LAST_INSERT_ID()的结果放入到传入的model的主键里面,
接口:
int insert(@Param("item")MybtisVO item);
<insert id="insert">
INSERT INTO mybtis(sname) VALUES (#{item.sname})
<!--selectKey 会将 SELECT LAST_INSERT_ID()的结果放入到传入的model的主键里面,
keyProperty 对应的model中的主键的属性名,这里是 user 中的id,因为它跟数据库的主键对应
order AFTER 表示 SELECT LAST_INSERT_ID() 在insert执行之后执行,多用与自增主键,
BEFORE 表示 SELECT LAST_INSERT_ID() 在insert执行之前执行,这样的话就拿不到主键了,
这种适合那种主键不是自增的类型
resultType 主键类型 -->
<selectKey keyProperty="MID" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
</insert>
重点代码:
<selectKey keyProperty="MID" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
若SQL语句都相同可以提取出来作为一个方法:
<sql id="sqlBase">
SELECT empno,ename,job,hiredate,sal FROM emp
</sql>
只需要在其他操作的xml语句后添加就可以引用了:
<select id="find" resultType="com.uplooking.pojo.EmpVO">
<include refid="sqlBase"/>
<trim prefix="WHERE" prefixOverrides="AND">
<if test="job!=null and job!=''">
AND job = #{job} <!-- 'SALESMAN' -->
</if>
<if test="sal!=null">
AND sal <= #{sal}
</if>
</trim>
</select>
引用自定义SQL语句:
<include refid="sqlBase"/>
自定义SQL:
当sql返回条件已经在文件里不存在时,此时需要自定义一个pojo类以用于接收返回值
映射配置文件:
<?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.uplooking.dao.EmpDO">
<cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>
<resultMap type="com.uplooking.pojo.GroupVO" id ="GroupMap">
<result column="number" property="tc"/>
<result column="name" property="job"/>
</resultMap>
<select id="count" resultType="int">
${sql}
</select>
<select id="count1" resultType="int">
select count(empno) from emp
</select>
<select id="countGroup" resultMap="GroupMap">
${sql}
</select>
<select id="countGroup1" resultMap="GroupMap">
select count(job) tc,job from emp group by job
</select>
</mapper>
自定义返回值实现类:
public class GroupVO {
private int number;
private String name;
实现:
SqlSession session =MybatisUtils.getSqlSession();
EmpDO empDO =session.getMapper(EmpDO.class);
String sql= "select count(empno) from emp";
System.out.println(empDO.count(sql));
System.out.println(empDO.count1());
System.out.println("----------------------------");
String sql1 ="select count(job ) tc ,job from emp group by job";
System.out.println(empDO.countGroup(sql1));
System.out.println(empDO.countGroup1());
end》》》
静下心来分析,代码就会越看越有趣
以上是关于Mybatis全解的主要内容,如果未能解决你的问题,请参考以下文章
SSM-MyBatis-05:Mybatis中别名,sql片段和模糊查询加getMapper