Mybatis随手笔记

167 阅读4分钟

Mybatis是一款优秀的持久层框架,主要就是封装了JDBC

将程序数据在持久状态和瞬时状态间转换的机制

优点:

  • 解除了sql与程序代码的耦合,通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,sql和代码的分离,提高了可维护性

经常使用技巧

1.第一个入门小案例

废话不多说,直接上代码

1.搭建实现数据库

CREATE DATABASE `mybatis`; USE `mybatis`; DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (  `id` int(20) NOT NULL,  `name` varchar(30) DEFAULT NULL,  `pwd` varchar(30) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert  into `user`(`id`,`name`,`pwd`) values(1,'王二','123456'),(2,'张三','abcdef'),(3,'李四','987654');

2.导jar包

<dependency>    <groupId>org.mybatis</groupId>    <artifactId>mybatis</artifactId>    <version>3.5.2</version></dependency><dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId>    <version>5.1.47</version></dependency>

3.编写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>    <environments default="development">        <environment id="development">            <transactionManager type="JDBC"/>            <dataSource type="POOLED">                <property name="driver" value="com.mysql.jdbc.Driver"/>                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>                <property name="username" value="root"/>                <property name="password" value="123456"/>            </dataSource>        </environment>    </environments>    <mappers>        <mapper resource="com/kuang/dao/userMapper.xml"/>    </mappers></configuration>

4.编写Mybatis工具类(以前是jdbc,现在主要封装了一下,写一个sqlsession的工具类)

import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;import java.io.InputStream;public class MybatisUtils {    private static SqlSessionFactory sqlSessionFactory;    static {        try {            String resource = "mybatis-config.xml";            InputStream inputStream = Resources.getResourceAsStream(resource);            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);        } catch (IOException e) {            e.printStackTrace();        }    }    //获取SqlSession连接    public static SqlSession getSession(){        return sqlSessionFactory.openSession();    }}

5.创建实体类

public class User {    private int id;  //id    private String name;   //姓名    private String pwd;   //密码    //构造,有参,无参    //set/get    //toString() }

6.编写Mapper接口类

import com.kuang.pojo.User;import java.util.List; public interface UserMapper {    List<User> selectUser();}

7.编写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.kuang.dao.UserMapper">  <select id="selectUser" resultType="com.kuang.pojo.User">    select * from user  </select></mapper>

8.编写测试类

public class MyTest {    @Test    public void selectUser() {        SqlSession session = MybatisUtils.getSession();        //方法一:        //List<User> users = session.selectList("com.kuang.mapper.UserMapper.selectUser");        //方法二:        UserMapper mapper = session.getMapper(UserMapper.class);        List<User> users = mapper.selectUser();        for (User user: users){            System.out.println(user);        }        session.close();    }}

2.CRUD操作及配置解析

根据id查询用户

1.dao层接口添加方法

public interface UserMapper {
    //查询全部用户
    List<User> selectUser();
    //根据id查询用户
    User selectUserById(int id);

2.在xml中添加查询语句

<select id="selectUserById" resultType="com.kuang.pojo.User">
  select * from user where id = #{id}
</select>

3.测试类中测试

@Test
public void tsetSelectUserById() {
    SqlSession session = MybatisUtils.getSession();  //获取SqlSession连接
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = mapper.selectUserById(1);
    System.out.println(user);
    session.close();
}

根据密码和名字查询用户

方式一:直接根据字段来进行查找(场景:参数少)

//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);
}


/*
    <select id="selectUserByNP" resultType="com.kuang.pojo.User">
      select * from user where name = #{username} and pwd = #{pwd}
    </select>
*/

方式二:使用万能的Map进行查找(场景:参数多)

User selectUserByNP2(Map<String,Object> map);

<select id="selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
  select * from user where name = #{username} and pwd = #{pwd}
</select>

方式三:直接用对象(场景:参数多)

User selectUserByNP2(User user);

<select id="selectUserByNP2" parameterType="com.kuang.pojo.User" resultType="com.kuang.pojo.User">
  select * from user where name = #{username} and pwd = #{pwd}
</select>

小总结:

  • 所有的增删改查操作都要提交事务

  • 接口中的所有普通参数,尽量写上@Param,尤其是多个参数时,必须写上,

  • 如果参数较多,则使用map,

  • 为了规范操作,尽量把Parameter参数和resultType都写上

3.核心配置文件

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
        environment(环境变量)
            transactionManager(事务管理器)
            dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
<!-- 注意元素节点的顺序!顺序不对会报错 -->

4.ResultMap及分页

属性名与字段名不一致问题的解决

  • 方法一:指定别名,别名和java实体类的属性名一致,pwd as password

  • 方法二:使用结果集映射--》ResultMap

使用limit实现分页

#语法
SELECT * FROM table LIMIT stratIndex,pageSize
 
SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15  
 
#为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.  
 
#如果只给定一个参数,它表示返回最大的记录行数目:   
SELECT * FROM table LIMIT 5; //检索前 5 个记录行  
 
#换句话说,LIMIT n 等价于 LIMIT 0,n。 

RowBounds分页

List<User> getUserByRowBounds();

<select id="getUserByRowBounds" resultType="user">
  select * from user
</select>


@Test
public void testUserByRowBounds() {
    SqlSession session = MybatisUtils.getSession();
 
    int currentPage = 2;  //第几页
    int pageSize = 2;  //每页显示几个
    RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);
 
    //通过session.**方法进行传递rowBounds,[此种方式现在已经不推荐使用了]
    List<User> users = session.selectList("com.kuang.mapper.UserMapper.getUserByRowBounds", null, rowBounds);
    for (User user: users){
        System.out.println(user);
    }
    session.close();
}

#{}和${}的区别

#{}的作用主要是替换预编译语句PrepareStatement中的占位符
${}的作用是直接进行字符串的替换
使用注解和配置文件的协同开发,才是Mybatis的最佳实践

5.一对多和多对一的处理

其实就是两个关键字的使用 association 和 collection,所以associationyon用于一对一和多对一,而collection用于一对多的关系

6.动态sql

直接上例子

select * from blog where title = #{title} and author = #{author}
-->
<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog where
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</select>

<!--注意set是用的逗号隔开-->
<update id="updateBlog" parameterType="map">
    update blog
      <set>
          <if test="title != null">
              title = #{title},
          </if>
          <if test="author != null">
              author = #{author}
          </if>
      </set>
    where id = #{id};
</update>

<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <choose>
            <when test="title != null">
                 title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>
                and views = #{views}
            </otherwise>
        </choose>
    </where>
</select>

7.缓存

首先明白一个问题:为什么会使用缓存,减少和数据库交互的次数,减少系统开销,提高系统效率

  • Mybatis包含一个非常强大的查询缓存特性,他可以非常方便地定制和配置缓存,缓存可以极大的提升查询效率

  • mybatis中默认定义了两级缓存:一级缓存和二级缓存

  • 默认情况下,只有一级缓存开启,sqlSession级别的缓存,也称为本地缓存

  • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存

  • 为了提高扩展性,mybatis定义了缓存接口,可以通过实现Cache接口来定义二级缓存