mybatis详解

mybatis学习最好是看官方文档学习
还不够详细,标题党了属于是,对不起!!!
mybatis官方文档
该网站难打开,可以多试试或是用流量打开

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

接下的项目是由maven来管理
maven下载与配置

一、入门

在这里插入图片描述

1)导包

pom.xml 中操作

  1. 连接数据库     mysql-connector-java.jar
  2. 使用mybatis     mybatis.jar
  3. 测试             junit.jar
  4. 快速实现get&set函数的插件  lombok.jar
<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
    </dependencies>

2)配置xml文件

resources 中操作

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

在这里插入图片描述

  • jdbc.properties (记录数据库连接的信息,引入mybatis-config.xml配置数据库)
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/你的数据库
username=你的账号
password=你的密码
  • 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>
    <!--引入数据库登录信息-->
    <properties resource="jdbc.properties"></properties>
    <!--事务管理和连接池的配置-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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>
    <!--映射器-->
    <mappers>
    <!--*.xml:你所注册绑定的Mapper.xml的全限定名-->
        <mapper resource="*.xml"/>
    </mappers>
</configuration>
  • mybatis工具类(为了获得SqlSession,在until文件夹下)
public class mybatisUntil {
    private static  SqlSessionFactory sqlSessionFactory;
    static{
        InputStream inputStream = null;
        try {
            String resource = "mybatis-config.xml";
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //返回SqlSession
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

3)pojo类和数据库

  1. 数据库表
    users表
    在这里插入图片描述

  2. pojo类 user

@Data                 //Lombok插件生成get&set函数
@AllArgsConstructor   //Lombok插件生成有参函数
@NoArgsConstructor    //Lombok插件生成无参函数
//当然以上可以不用,手动生成也可以
public class user {
    private int id;
    private String uname;
    private String upassword;
}

4)Mapper接口&Mapper.xml

在这里插入图片描述
userMapper 接口的方法名和userMapper.xml的代号需要一致

  • userMapper 接口
public interface userMapper {
    //查询所有users表中的数据
    public List<user> selectAll();
}
  • userMapper.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">
<!--报错“Type interface lzk.dao.userMapper is not known to the MapperRegistry” 原因: 路径间隔是.-->
<mapper namespace="lzk.dao.userMapper">
    <!--id:给该sql映射一个代号 resultType:返回的值的数据类型-->
    <select id="selectAll" resultType="lzk.pojo.user">
    select * from users
  </select>
</mapper>

在mybatis-config.xml添加映射

<!--映射器-->
    <mappers>
        <!--resource:userMapper.xml在resources的路径-->
        <mapper resource="userMapper.xml"/>
    </mappers>

5)测试

public class test {
    @Test
    public void test01(){
        //获取SqlSession用于执行sql
        SqlSession sqlSession= mybatisUntil.getSqlSession();
        //获得mapper映射器实例
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //执行sql
        List<user> userList=userMapper.selectAll();
        //输出
        for (user user : userList) {
            System.out.println(user);
        }
        //关闭SqlSession
        sqlSession.close();
    }
}

在这里插入图片描述


二、增删改查

对数库进行操作只要对Mapper接口&Mapper.xml进行修改即可
因为是执行事务,所以没有进行事务提交就没有真正进行数据更改。Therefore,用sqlSession.commit()提交事务在insert、update、delete时

insert

//Mapper接口
  //增加一条记录
    public int insertInUsers(user user);
    
//Mapper.xml
//parameterType:参数的数据类型
<insert id="insertInUsers" parameterType="lzk.pojo.user" >
        //#{id},#{unmae},#{upassword}对应pojo类属性名
        insert into users values(#{id},#{unmae},#{upassword})
</insert>

//测试
@Test
    public void test02(){
        //获取SqlSession用于执行sql
        SqlSession sqlSession= mybatisUntil.getSqlSession();
        //获得mapper映射器实例
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //执行sql
        int insert=userMapper.insertInUsers(new user(4,"柯基","444"));
        //提交事务
        if(insert>0)sqlSession.commit();
        //关闭SqlSession
        sqlSession.close();
    }

在这里插入图片描述

update

//Mapper接口
 //修改一条记录
    public int updateAll(user user);
    
//Mapper.xml
<update id="updateAll" parameterType="lzk.pojo.user">
        update users set unmae=#{unmae},upassword=#{upassword} where id=#{id}
    </update>

//测试
@Test
    public void test03(){
        //获取SqlSession用于执行sql
        SqlSession sqlSession= mybatisUntil.getSqlSession();
        //获得mapper映射器实例
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //执行sql
        int update=userMapper.updateAll(new user(4,"keji","123"));
        //提交事务
        if(update>0)sqlSession.commit();
        //关闭SqlSession
        sqlSession.close();
    }

在这里插入图片描述

delete

//Mapper接口
 //删除一条记录
    public int deleteById(int id);
    
//Mapper.xml
<delete id="deleteById" parameterType="int">
        <!--#{id}对应参数id-->
        delete from users where id=#{id}
    </delete>

//测试
@Test
    public void test04(){
        //获取SqlSession用于执行sql
        SqlSession sqlSession= mybatisUntil.getSqlSession();
        //获得mapper映射器实例
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //执行sql
        int delete=userMapper.deleteById(4);
        //提交事务
        if(delete>0)sqlSession.commit();
        //关闭SqlSession
        sqlSession.close();
    }

在这里插入图片描述

select多表

resultMap:
association – 一个复杂类型的关联;许多结果将包装成这种类型
嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
collection – 一个复杂类型的集合
嵌套结果映射 – 集合可以是 resultMap 元素,或是对其它结果映射的引用

在这里插入图片描述

//mysql
create table teacher(
    tid int PRIMARY key,
	tname varchar(20)
);
create table student(
    sid int PRIMARY key,
	sname varchar(20),
	spassword varchar(15),
	tid int,
	foreign key (tid) REFERENCES teacher(tid)
);

在这里插入图片描述

一个老师教授n个学生 (一对多)

生成student和teacher类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class student {
    private int sid;
    private String sname;
    private String spassword;
    private int tid;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class teacher {
    private int tid;
    private String tname;
    private List<student> students;
}
//Mapper接口
 public teacher TAndS(int id);
 
//Mapper.xml
<select id="TAndS" resultMap="teacherAstudent">
        select *
          from student join teacher on student.tid=teacher.tid
          where teacher.tid=#{id}
    </select>
    <resultMap id="teacherAstudent" type="lzk.pojo.teacher">
        <result property="tid" column="tid"></result>
        <result property="tname" column="tname"></result>
        <collection property="students" ofType="lzk.pojo.student">
            <result property="sid" column="sid"></result>
            <result property="sname" column="sname"></result>
            <result property="spassword" column="spassword"></result>
            <result property="tid" column="tid"></result>
        </collection>
    </resultMap>

//测试
@Test
    public void test05(){
        //获取SqlSession用于执行sql
        SqlSession sqlSession= mybatisUntil.getSqlSession();
        //获得mapper映射器实例
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //执行sql
        teacher teacher = userMapper.TAndS(1);
        System.out.println(teacher);
        //关闭SqlSession
        sqlSession.close();
    }

n个学生由一个老师教导 (多对一)

生成student和teacher类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class student {
    private int sid;
    private String sname;
    private String spassword;
    private teacher teacher;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class teacher {
    private int tid;
    private String tname;
}
//Mapper接口
 //多对一
    public student TAndS();
 
//Mapper.xml
<select id="SAndT" resultMap="studentAteacher">
        select *from student join teacher on student.tid=teacher.tid
    </select>
    <resultMap id="studentAteacher" type="lzk.pojo.student">
        <result property="sid" column="sid"></result>
        <result property="sname" column="sname"></result>
        <result property="spassword" column="spassword"></result>
        <association property="teacher" javaType="lzk.pojo.teacher" >
            <result property="tid" column="tid"></result>
            <result property="tname" column="tname"></result>
        </association>
    </resultMap>

//测试
 @Test
    public void test06(){
        //获取SqlSession用于执行sql
        SqlSession sqlSession= mybatisUntil.getSqlSession();
        //获得mapper映射器实例
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //执行sql
        List<student> studentList = userMapper.SAndT();
        for (student student : studentList) {
            System.out.println(student);
        }
        //关闭SqlSession
        sqlSession.close();
    }

在这里插入图片描述

三、xml配置

mybatis-config.xml中configuration的配置顺序要按如下顺序

在这里插入图片描述

settings

日志

设置名:  logImpl
描述:  指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
有效值:  SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
默认值:  未设置
功能:打印并记录你对数据库的操作

  • STDOUT_LOGGING
//mybatis-config.xml
<settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

在这里插入图片描述

  • LOG4J

1、导包

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

2、log4j.properties(log4j配置信息)

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c}-%m%n

#文件输出的相关设置 ./log/lzk.log:在根目录下创建log(装载日志文件lzk.log)
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/lzk.log 
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

3、日志选择

<settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

在这里插入图片描述
并生成日志
在配置中设置文件位置等信息
在这里插入图片描述

typeAliases(类别名)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。在要输入全限定名时,输入type后的别名即可。例如:

<settings>***</settings>
//typeAliases要在setting下面设置
  <typeAliases>
        <typeAlias type="userMapper" alias="lzk.dao.userMapper">   </typeAlias>
    </typeAliases>

四、注解开发

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

1)注册映射

//mybatis-config.xml
<mappers>
        //studentMapper接口
        <mapper class="lzk.dao.studentMapper"/>
    </mappers>

2)书写语句

//studentMapper接口
public interface studentMapper {
    @Select("select * from student")
    List<student> getAllStudent();
    @Insert("insert into student values(#{id},#{sname},#{spassword},#{tid})")
    int insertInStudent(student student);
    @Update("update users set sname=#{sname},spassword=#{spassword} where id=#{uid}")
    int updateById(@Param("uid") int id);
    //@Delete("***")   
}

注意
在这里插入图片描述

测试

 @Test
    public void test07(){
        //获取SqlSession用于执行sql
        SqlSession sqlSession= mybatisUntil.getSqlSession();
        //获得mapper映射器实例
        studentMapper studentMapper=sqlSession.getMapper(studentMapper.class);
        //执行sql
        List<student> studentList = studentMapper.getAllStudent();
        for (student student : studentList) {
            System.out.println(student);
        }
        //关闭SqlSession
        sqlSession.close();
    }

在这里插入图片描述

五、动态sql

使用类似jstl中的if、choose、foreach达到动态组成sql的效果

//引子
如何做到操作时根据参数动态操作数据?
1、没有参数时可以操作全部
2、有参数是可以根据参数的限制操作

查询sql语句: select * from users
上面显然是不能满足所有的要求

下面用官方文档的例子

if

<!--都能去掉标签内的一些错误以达到sql语句无错-->
<where></where>
//只有尖括号的内容不为空才显示

<set></set>
//和<where> 一样

<if 关系式 ></if>
//关系式为真才显示尖括号的内容

//<when><if>同理
<choose>
    <when 关系式>内容1</when>
    <when 关系式>内容2</when>
    <otherwise>内容3</otherwise>
</choose>
//和switch一个理

foreach   使用场景是对集合进行遍历

<select id="findActiveBlogWithTitleLike" resultType="Blog">
  SELECT * FROM BLOG 
  <where>
	  <if test="title != null">
	    AND title like #{title}
	  </if>
  </where>
</select>
<!--
查询BLOG表,
若参数title == null sql语句为 SELECT * FROM BLOG 
反之sql语句为  SELECT * FROM BLOG where title like #{title}

注意  在<if>可以除去多余的and、or等
-->

choose

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>
<!--
查询BLOG表,
若参数title != null sql语句为 
SELECT * FROM BLOG WHERE state = ‘ACTIVE’ and title like #{title}
若参数author != null and author.name != null sql语句为
SELECT * FROM BLOG WHERE state = ‘ACTIVE’ AND author_name like #{author.name}
反之sql语句为 SELECT * FROM BLOG WHERE state = ‘ACTIVE’   AND featured = 1

注意  在<when>也可以除去多余的and、or等
-->

foreach

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

<!--
查询POST表,别名为P,
SELECT * FROM POST P WHERE ID in (内容)
遍历list集合,获得所有对象内容
item="item"                        遍历到的对象
index="index"      				   遍历的次数
collection="list"  				   集合类型
open="(" separator="," close=")"   给所获得内容外加一个(),每个数据项之间用','隔开
-->

六、缓存

类似操作系统内存管理中分页、分段中的快表,记录寻找过的数据在缓存中,若下次寻找先找缓存,若没有再执行sql语句查询,减少开销

<!--
更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
-->
<cache
<!---在缓存中的数据项满了的替换方式,类似页面置换算法->
  eviction="FIFO" 
  flushInterval="60000"
  size="512"
  readOnly="true"/>

开启和设置

<!---mybatis-config.xml->

<!---默认一级缓存是开启的->
<settings>
        <setting name="cacheEnabled" value="true"/>
</settings>
<!---设置,开启二级缓存->
<cache
  eviction="FIFO" 
  flushInterval="60000"
  size="512"
  readOnly="true"/>

一级缓存&二级缓存

在这里插入图片描述

注意缓存失效

  1. 执行增删改会刷新缓存
  2. 手动清楚缓存

终于搞完!
更多详情请看官方文档!
若有错,请大家指出!
【回见】

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值