mybatis 入门教程

简介

mybatis框架封装了数据层(Dao),对应Java基础中的JDBC部分。将JDBC中重复的连接数据库获取数据的代码进行了整合,其中的变量(例如:数据库地址,账号,密码,想执行的sql等)通过xml文件配置,让开发专注在业务逻辑上,屏蔽底层大量冗余的代码。

流程简述

MyBatis 的 XML 配置文件(名字自取,本篇为mybatisConfig.xml)包含了全局的设置和mapper映射,通过读取xml配置文件,SqlSessionFactoryBuilder可以创建一个SqlSessionFactory,SqlSessionFactory用于创建SqlSession, 通过用 SqlSession 实例来执行从mapper.xml中映射的SQL 语句。大致流程如下:
在这里插入图片描述
最简单的调用demo:

public class BaseTest {
    public static void main(String[] args) {

        String resource = "mybatisConfig.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            //读取全局XML 映射配置文件创建工厂
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //生产SqlSession
            SqlSession session=sqlSessionFactory.openSession();
            //通过SqlSession执行mapper.xml中映射的sql
            List<SysUser> list = session.selectList("com.mybatis.mapper.SysUserMapper.selAll");
            for (SysUser user : list) {
                System.out.println(user.toString());
            } 
            //事务处理
            //session.rollback();
            //session.commit();
            //释放资源
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

环境搭建

1,Ant项目:自行下载jar包,添加mybatis-x.x.x.jar

2,Maven项目:pom.xml中添加依赖

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.3.0</version>
</dependency>

开发配置

XML 全局配置文件——mybatisConfig.xml

作为mybais的全局配置,其中所有的标签都必须按照流程简述中的顺序写,否则会报错。

properties

定义属性,如下面这段代码中定义的属性,在整个全局配置xml文件中可以通过${username} ${password}来引用

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>
--
resource属性引用的properties配置文件路径
property标签定义的属性

若两者存在同名属性,resource引用的配置文件中的属性由于是后加载会覆盖property标签中属性的值

settings

有很多设置,后续用到会补充,目前暂时设置一个日志

    <settings>
		<!--mybatis日志启用配置-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>

typeAliases

给数据库对应的实体类(pojo)定义一个别名,就不用全路径引用

<typeAliases>
<!--给某个类定义一个别名(区分大小写)-->
    <typeAlias type="com.mybatis.pojo.SysUser" alias="user"/>
<!--定义一个包,则类可以直接通过类名(不区分大小写)引用-->
    <package name="com.mybatis.pojo"/>
</typeAliases>

environments

配置数据库连接信息

<!--default引用environment的id,当前使用的环境 -->
<environments default="default">
    <!--声明可使用的环境 -->
    <environment id="default">
        <!--使用原生JDBC事务 / MANAGED 事务管理转交给其他容器-->
        <transactionManager type="JDBC"/>
		<!--POOLED:使用数据库连接池(tomcat的context.xml文件需要配置)
            UNPOOLED:不实用数据库连接池,和直接使用 JDBC 一样
            JNDI:java 命名目录接口技术-->
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/zee"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

mappers

定义对应的mapper.xml文件,mapper.xml文件是mybatis的核心,定义了sql映射语句,此处可以使用相对于类路径的资源引用,或者字符表示,或 url 引用的完全限定名。

<mappers>
    <!--配置某个xml文件映射-->
    <mapper resource="com/mybatis/mapper/UserMapper.xml"/>
    <!--配置一个包路径,包里所有的xml文件都自动注册映射-->
    <package name="com.mybatis.mapper"/>
</mappers>

Mapper XML 文件

这里是整个mybatis的核心,日常开发中就是在此处编写sql,可以想象成一个DAO层的实现类。

<!-- namesapce:理解成dao层的实现类的全路径(包名+类名) -->
<mapper namespace="com.mybatis.mapper.SysUserMapper" >
</mapper>

sql标签

提取重复sql语句

<sql id="userColumns"> id,username,password </sql>

<select id="selectUsers" parameterType="int" resultType="hashmap">
  select <include refid="userColumns"/>
  from some_table
  where id = #{id}
</select>

cache

缓存可以减少与数据库的交互,提高反应速度

  • 一级缓存——同一个SqlSession执行同一个方法只会跟数据库交互一次,第一次之后把查询结果缓存到SqlSession缓存区(mybatis默认开启)
  • 二级缓存——同一个SqlSessionFactory内的所有SqlSession共享一个缓存区
    通过在mapper.xml文件中添加:
<cache readOnly="true"></cache>
  • 自定义缓存——实现Cache接口,可以自定义缓存方式,可配置redis等NOSQL数据库

select ,insert, update,delete标签

对应sql语句,通过属性可以根据业务逻辑来定义sql

select ,insert, update,delete标签使用方法类似

<mapper namespace="com.mybatis.mapper.SysUserMapper" >
    <select id="selById" resultType="user" parameterType="int">
		select * from sys_user s where s.id=#{param1}
    </select>
</mapper>
属性作用
id相当于实体类的方法名
resultType相当于方法的返回值,查询sql返回的是一个结果集,此处写其中一条结果对应的java类(pojo可以应用typeAliases定义的别名)
parameterType相当于方法的参数

使用parameterType传参遵循以下规则:

基础数据类型/String#{xxx}:使用parameterType传送一个基础数据类型参数随便填都可以正确传入参数
Map#{key}:通过key来占位
List#{list[0]}:通过#{list[index]}来用list中某一条数据占位
对象#{pror}:通过属性(自动调用属性的get方法)自动匹配占位

对于map和对象也可以通过${key} ${pror}来拼接sql,但是这种方式在底层是通过字符串直接拼接,存在sql注入风险

resultMap

从数据库的数据到javaBean的对象,使用resultType属性时,是利用了Auto-Mapping特性,底层是自动把sql查询出来的字段和resultType指定的类的属性对应,调用set方法封装,而如果程序员想要自己定义mapping,可以采用resultMap属性。

动态SQL

在编写上面的sql时,有时业务需求要根据传入参数细微调整sql,因此有多个标签帮助用于动态构建sql

  1. 判断
    if
    条件为true则在sql中拼接标签内的内容
<select id="selByIdByName" resultType="com.mybatis.pojo.Student">
   	select * from student where 
   	<!--条件判断-->
   	<if test="id != null and id !=''">
   		and id = #{id}
   	</if>
   	<if test="name != null and name !=''">
   		and name = #{name}
   	</if>
</select>

choose, when, otherwise
类似于java中的switch,case;只会有一个条件满足被拼接在sql后

<select id="selByIdByName" resultType="com.mybatis.pojo.Student">
	select * from student
	<where>
		<!--多个条件只成立一个-->
		<choose>
			<when test="id != null and id !=''">and id = #{id}</when>
			<when test="name != null and name !=''">and name = #{name}</when>
			<otherwise>and 1=1</otherwise>
		</choose>
	</where>
</select>
  1. 消除
    对于上面的if中的例子,拼接出来的sql会报错,应为where后面直接接了and,mybatis提供了消除这种错误的方式
    where
    会自动去除where后面跟的and或者or等关键字
 <select id="selByIdByName" resultType="com.mybatis.pojo.Student">
		select * from student 
	<where>
		<!--条件判断-->
		<if test="id != null and id !=''">
			and id = #{id}
		</if>
		<if test="name != null and name !=''">
			and name = #{name}
		</if>
	</where>
</select>

set
在update语句中set会遇到跟where一样的多出来and的一样的情况多出来,

<update id="updateById" parameterType="com.mybatis.pojo.Student">
		update student
		<!--自动拼接set并智能去除后面的,-->
		<set>
			<if test="name != null and name !=''">name = #{name},</if>
		</set>
</update>

trim
如业务上有其他需求可以通过trim来实现自定义拼接和去除

属性用途
prefix前缀加
prefixOverrides前缀去除(通过|管道来定义多个,空格是必须的)
suffix后缀加
suffixOverrides后缀去除

例如where标签就等价于

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ... 
</trim>

set标签等价于

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>
  1. 循环——foreach
    在parameterType传参的小节中,没有list这种参数,集合参数的方法已经被内置在底层中,比如list.size() lise.isEmpty() 等都可以直接调用,作为if的判断依据,
	<select id="selInById" parameterType="list" resultType="Student">
		select * from student
		<where>
			<if test="list !=null and list.size > 0">
				id in 
				<foreach collection="list" item="item" open="(" separator="," close=")">
					#{item}
				</foreach>
			</if>
		</where>
	</select>
属性用途
collectionList对象默认用"list"代替作为键,数组对象有"array"代替作为键,若作为map中的一个键值对传入,则以map中的key作为键,如有注解则使用注解定义的name
item集合中元素迭代时的别名
index在list和数组中,index是元素的序号,在map中,index是元素的key
openforeach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选
separator元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开
closeforeach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
  1. bind
    创建一个变量并绑定在ognl的Context中 value中的内容按XML格式解析,后面引用的id的值都变成bind之后的value
<select id="selByIdByName" resultType="com.mybatis.pojo.Student">
		select * from student where id like 
		<!--bind标签:-->
		<bind name="id" value="&apos;%'+id"/>
		#{id}<!---->
</select>

使用方式

直接调用

在最开始的流程简述时,我们使用的是一种通用的调用方式,通过SqlSession的方法去执行mapper.xml中的映射sql:

List<SysUser> list = SqlSession.selectList("com.mybatis.mapper.SysUserMapper.selAll");

接口绑定

使用接口绑定可以简化调用过程,避免重复的写mapper映射的类名,那接口绑定是什么东西呢?
前面我们把一个mapper.xml配置文件想象成一个实体类,如果给这个实体类定义一个接口,那么java多态的性质可以让我们使用接口来操作实体类(mapper.xml)里的方法。

具体操作起来很简单:

  1. 定义一个mapper.xml文件
<!--通过接口绑定则namespace要对应到接口-->
<mapper namespace="com.mybatis.mapper.StudentMapper" >
	<select id="selAll" resultType="com.mybatis.pojo.Student">
		select * from student
	</select>
</mapper>
  1. 定义一个接口
    接口的路径要与mapper.xml文件中的namespace一致
    接口的方法名要于mapper.xml文件中的id一致
package com.mybatis.mapper;

import com.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface StudentMapper {
    List<Student> selAll();
 }
  1. 调用
public class MapperBindInterfaceTest {
    public static void main(String[] args) {
        String resource = "mybatisConfig.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream("mybatisConfig.xml");
            SqlSessionFactory sqlSessionFactory =
                    new SqlSessionFactoryBuilder().build(inputStream);
            //生产SqlSession
            SqlSession session=sqlSessionFactory.openSession();
            //通过session获取实体类对应的mapper的接口
            StudentMapper mapper = session.getMapper(StudentMapper.class);
           //通过接口调用方法来操作mapper中定义的方法,执行sql
            //原理:jdk的动态代理设计模式,创建了实现该接口的代理实现类
           List<Student> students = mapper.selAll();
            for(Student s:students){
                System.out.println(s);
            }
    		//释放资源
            session.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

参数传递

通过前面得学习已经可以基本使用mybatis框架做简单的查询,但是使用parameterType只能传入单个参数,而在接口绑定部分我们将mapper.xml与接口联系起来,将id与接口方法联系起来,那么在接口中定义多个参数的时候,是可以直接传入多个参数的比如:
接口

package com.mybatis.mapper;

import com.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface StudentMapper {
		//不使用注解
        List<Student> selInById(int id,String name,Map<String,Object> map);
        //使用注解
        //List<Student> selInById(@Param("id") int id,@Param("name") String name,@Param("stus") Map<String,Object> map);
}

mapper.xml文件:此时可以不用写parameterType

多参数的占位写法规则:

  • 不使用注解:
    只能使用#{0}#{param1}这种顺序占位,若参数为Map,Javabean时,可以使用#{0.key}或者#{param1.pror}来获取参数
<?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.mybatis.mapper.StudentMapper" >
<select id="selInById"  resultType="Student">
		select * from student where id = #{0} and name = #{param2} and id = #{2.id}
	</select>
</mapper>
  • 使用注解
    使用#{name}占位,name为接口定义的注解里面的name。若参数为Map,List,JavaBean,都可以按parameterType中同样的方式占位,如#{stus.id}
<?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.mybatis.mapper.StudentMapper" >
<select id="selInById"  resultType="Student">
		select * from student where id = #{id} and name = #{name} and id = #{stus.id}
	</select>
</mapper>

调用

public class DynamicSqlTest {
    public static void main(String[] args) {
        String resource = "mybatisConfig.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //生产SqlSession
            SqlSession session=sqlSessionFactory.openSession();
            //通过session获取实体类对应的mapper的接口
            StudentMapper mapper = session.getMapper(StudentMapper.class);
            Map m = new HashMap();
            m.put("id","1");
            List<Student> students = mapper.selInById(1,"haoze",m);
            System.out.println(students);
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

mybatis注解

在使用接口绑定的时候,我们可以使用注解来帮忙简化mapper.xml的配置。

在XML 映射配置文件——mybatisConfig.xml中配置mappers

<mappers>
	<!-- 使用class属性则完全抛弃mapper.xml文件配置-->
	  <mapper class="com.mybatis.mapper.StudentMapper"/>
	  <!--使用package则注解和mapper.xml都可以起作用-->
	  <package name="com.mybatis.mapper"/>
</mappers>

在绑定的接口中使用注解。

package com.mybatis.mapper;

import com.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

public interface StudentMapper {
    @Select("select * from student")
    List<Student> selAll();
 }	

若通过注解方式定义sql,那么mapper.xml中不要定义对应方法,否则会报错:

Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.mybatis.mapper.StudentMapper.selAll

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值