栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

mybatis

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

mybatis

文章目录
  • 1.mybatis
    • 1.1mybatis使用
    • 1.2 为什么使用mybatis
  • 2.第一个mybatis程序
    • 2.1 搭建环境
    • 2.2创建子模块
  • 3.CURD
    • map
    • 模糊查询
  • 4.配置解析
    • 4.1 配置环境
    • 4.2 配置文件
    • 别名
    • 4.3 设置
    • 4.4 映射器
    • 4.5 生命周期和作用域
  • 5.ResultMap结果集
  • 6.日志
    • 6.1 日志工厂
    • 6.2 log4j
  • 7.分页
    • 7.1 使用limit分页
    • 7.2 RowBounds
    • 7.3 分页插件
  • 8.使用注解开发
    • 8.1 面向接口
    • 8.2.mybatis执行流程
    • 8.3 CRUD注解开发
    • 8.4Lombok
  • 9.多对一处理
    • 9.1 嵌套子查询处理
    • 9.2 结果集查询处理
  • 10.一对多处理
    • 10.1嵌套子查询
    • 10.2 结果集查询
  • 11动态sql
    • 11.1自动生成id
    • 11.2动态sql
      • if
      • choose
      • set
      • sql片段
      • forEach
      • 实例
  • 12 缓存
    • 12.1 一级缓存
    • 12.2 二级缓存
    • 12.3 缓存原理
    • 12.4 自定义缓存ehcache
    • 12.1 一级缓存
    • 12.2 二级缓存
    • 12.3 缓存原理
    • 12.4 自定义缓存ehcache

1.mybatis

是一个持久层框架,通过XML配置或者注解配置,省去了所有的JDBC代码(除了sql语句),比如获取连接,设置参数,返回结果集。

开源在githup上

1.1mybatis使用
  1. maven仓库

    
        org.mybatis
        mybatis
        3.5.6
    
    
    
  2. GitHub

    Releases · mybatis/mybatis-3 · GitHub

  3. 中文文档

    ​ MyBatis中文网

1.2 为什么使用mybatis

自动化配置,实现sql和java代码分离,提高维护性。

2.第一个mybatis程序

搭建环境–》导入mybatis–》编写代码–》测试

2.1 搭建环境
  1. 创建maven项目

  2. 删除src目录,就可以当成maven的父目录,父目录中的依赖可以不用导入

  3. 导入maven依赖

        
    
    
            
            
                org.mybatis
                mybatis
                3.5.2
            
    
            
            
                mysql
                mysql-connector-java
                8.0.12
            
    
            
            
                junit
                junit
                4.12
                test
            
    
        
    
    • dependencies使用
    2.2创建子模块
    1. resources目录下配置mybatis核心配置文件,连接数据库
    
    
    
        
            
                
                
                    
                    
                    
                    
                
            
        
        
            
        
    
    

        
    

不要忘记mapper.xml的注入会报错

org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

//中文问题,mysql数据库中需要用utf8,将utf-8改为utf8

2.编写mybatis工具类,获取sqlSession相当于connection

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            //获取sqlSessionFactory,固定代码
            String resource = "mybatis_config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //通过sqlSessionFactory获取sqlSession
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();

    }
}

3.编写代码

实体类

public class User {
    private int id;
    private String name;
    private String pwd;

    public User() {
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", pwd='" + pwd + ''' +
                '}';
    }
}

2.接口类

public interface UserDao {
    List getUsers();
}

3.接口实现类




    
        select * from users where id = 1;
    

4.测试

public class UserDaoTest {
    @Test
    public void test(){
        //获取sqlSession
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //获取接口UserDao,调用方法
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List users = mapper.getUsers();
        //输出
        for(User user:users){
            System.out.println(user);
        }
    }
}

细节

*static静态代码块其实完全可以看做是一个没有名字、没有参数、没有返回值的静态方法*

SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;

代码优化

return sqlSessionFactory.openSession();

常见错误

  1. sql查询语句标签名

  2. jdbc数据库连接url

  3. 编码,mapper.xml和mybatis-config.xml中中文乱码问题

  4. mybatis中mapper.xml注册资源路径

  5. mapper.xml文件导出的问题,maven中pom.xml中需要扫描导出

        
        
            
                
                    src/main/resources
                    
                        ***.xml
                    
                    true
                
                
                    src/main/java
                    
                        ***.xml
                    
                    true
                
            
        
    
3.CURD

只需要修改接口,接口实现类,测试类

1.实现接口,UserMapper

public interface UserMapper {
    List list();
    User getUserById(int id);
    int addUser(User user);
    int updateUser(User user);
    int deleteUser(int id);
}
  • 参数
  • 返回值
  • 方法名规范

2.接口实现类 mapper.xml




    
        select * from users where id=#{id}
    
    
        insert into users (`id`,`name`,`pwd`) values (#{id},#{name},#{pwd})
    
    
        update users set `name`=#{name},`pwd`=#{pwd} where id=#{id}
    
    
        delete from users where id=#{id}
    

  • nameplace 空间命名对应接口,相当于实现接口
  • id对应方法名,相当于实现方法
  • 返回类型和参数
  • {id}可以获取对象中的属性,且要和对象属性一一对应
  • 表名前加数据库名,idea连接数据库后,没连不用写,直接写表名

3.测试

import com.qiang.dao.UserMapper;
import com.qiang.pojo.User;
import com.qiang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;

import java.util.List;

public class test {
    @Test
    public void test(){
        //获取sqlSession
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //获取接口UserDao,调用方法
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List users = mapper.list();
        User user1 = mapper.getUserById(1);
        //输出
        for(User user:users){
            System.out.println(user);
        }
        System.out.println(user1);
        sqlSession.close();
    }
    @Test
    public void addUserTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.addUser(new User(4,"lixin","123456"));
        if(i>0){
            System.out.println("插入成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    public void updateUserTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.updateUser(new User(4, "程咬金", "123456"));
        if(i>0){
            System.out.println("更改成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.deleteUser(3);
        if(i>0){
            System.out.println("删除成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }
}

  • 增删改要提交事务
  • 记得释放资源sqlSession
  • @Test
  • 传值 new User(4,“fewhi”,“5113”) 双引号
map

修改某一字段,如果字段过多,使用User传值,需要写出全部的字段,使用map最多传个id,随意简便。

使用User

mapper.updateUser1(new User(1,"王昭君","123456"));

使用map 键值对 key

int updateUser(Map map);

    update users set `name`=#{onename} where id=#{oneid}

 @Test
    public void updateTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        HashMap map = new HashMap<>();
        map.put("oneid", 1);
        map.put("onename", "宋尚香");
        mapper.updateUser(map);
        sqlSession.commit();
        sqlSession.close();
    }
  • 简便,省去过多字段
  • 不用像User一样,需要一一对应属性名,可以自定义

map传参数,sql中用key 【 parameterType=“Map”】

对象传参数,sql中用属性 【parameterType=“pojo.User”】

只用一个基本属性,比如int 【parameterType=“int”】省略不写

多个属性使用map或者注解

模糊查询
List getUserLike(String value);
select * from users where `name` like #{value}   
List users = mapper.getUserLike("李%");
  • 不安全,用户传入id为1&1=1,字符串拼接,存在注入问题

解决:可以把值固定,只能传value值

select * from users where `name` like "%"#{value}"%"
List users = mapper.getUserLike("李");
4.配置解析

不是是会简单的curd,学会配置,学会看官方文档

4.1 配置环境

可以配置多种环境,但是一个实例中只能选择一种环境,要通过default指定要使用的环境






    
    
        
            
            
                
                
                
                
            
        
    
    
4.2 配置文件

1.在resources文件中写db.properties文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_study?useSSL=false&useEncoding=true&characterEncoding=utf8&serverTimezone=UTC
username=root
password=123456

2.引入配置文件

//第一种方式 自闭合

//第二种方式 可以设置属性 优先级低于properties中

  
  

注意位置,应最前面,xml中的配置有顺序

properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?

别名

解决mapper.xml配置文件中类名复杂的问题

1.指定具体,适用于别名较少的

    
        
    

2.通过扫描包下所有的JavaBean类,默认为类名小写,首字母大写好像也行,适用于类多的情况


        
    

3.注解,可以在类中通过注解指定别名

@Alias("hello")
4.3 设置

4.4 映射器

注册绑定mapper文件

1.使用resources


        
    

2.使用class类名


        
    
  • 类名和配置名要相同,且在同一包下

3.使用package


        
    
4.5 生命周期和作用域

错误的使用作用域和生命周期,会引发并发问题

SqlSessionFactoryBuild

  • 创建SQLSessionFactory,创建玩就不需要了

  • 局部变量

  • sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    

SqlSessionFactory

  • 理解为数据库连接池

  • 创建sqlSession,需要一直存在,应用启动就一直存在

  • 全局变量,应用作用域

  • private static SqlSessionFactory sqlSessionFactory;
    return sqlSessionFactory.openSession();
    

sqlSession

  • 理解为一个请求

  • 调用方法,接口,实现业务

  • 在方法体类

  • public void getUsers(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List users = mapper.getUsers();
            for(User user :users ){
                System.out.println(user);
            }
    

每一个mapper相当于业务。实现SQL语句

5.ResultMap结果集

解决;属性名和字段名不一致问题,查询不到数据

解决方法一:给字段起别名

select `id`,`name`,`pwd` as `password` from users

解决方法二:resultMap结果集映射

    

        
        
        
    

resultMap结果集

  • 简单语句可以做到0配置,复杂语句只要说明关系
6.日志 6.1 日志工厂

解决SQL语句报错,方便找到bug

配置日志

    
        
    
  • 类名和值要严格,大小写,不能有空格
  • 默认为STDOUT_LOGGING 适用其他日志需要导入包

6.2 log4j

定义

log4j是Apache下的一个开源项目,可以通过修改配置文件,控制日志文件的输出方式,控制台,文件,和控制日志的格式,同时能通过Logger对象来定义日志信息的级别,输出,debug,error,更加清除生成过程

1.导入log4j包


    log4j
    log4j
    1.2.17


2.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

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/qiang.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.设置log4j

    

        
    

4.使用

使用

尽量只用log4j,配置文件可以想自定义修改,可以在log文件中通过前缀看到信息方式

1.在需要使用log4j的类中导入import org.apache.log4j.Logger;,一定是apache下的

2.日志对象,参数为当前类中的class

static Logger logger = Logger.getLogger(UserMapperTest.class);

3.实现级别

logger.info("输出");
logger.debug("debug");
logger.error("错误");
7.分页

减少数据库的压力,提高用户体验

7.1 使用limit分页
SELECt * FROM users LIMIT 0,2

本质是通过mybaties对SQL语句的实现

1.Usermapper

//分页
    List getUserByLimit(Map map);

2.UserMapper.xml


select * from users limit #{startIndex},#{pageSize}

3.test

    @Test
    public void getUserByLimitTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap map = new HashMap<>();
        map.put("startIndex", 0);
        map.put("pageSize", 2);
        List users = mapper.getUserByLimit(map);
        for(User user:users){
            System.out.println(user);
        }
    }
  • 通过map实现,Map的别名

7.2 RowBounds

1.接口

List getUsersByRowBounds();

2.接口实现类

    
        select * from student
    
    
        
        
        
    
    
        select s.id sid,s.name sname,t.name tname
        from student s,teacher t
        where s.tid=t.id
    
    
        
        
        
            
        
    
10.一对多处理

一个老师关联多个学生

10.1嵌套子查询
    
        select `id`,`name`,`tid` from student where tid=#{tid}
    
  • 两个条件
10.2 结果集查询
    
        select * from blog
        



        
            and author=#{author}
        
        
    


public class BlogTest {
    @Test
    public void queryBlogTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap<>();
        map.put("title", "python");
        map.put("author", "后羿");
        List blogs = mapper.queryBlog(map);
        for(Blog blog:blogs){
            System.out.println(blog);
        }
    }
}
choose