• Mybatis(1)—— 快速入门使用持久层框架Mybatis


    ​🏠​ 个人主页:csdn春和
    📚 推荐专栏:更多专栏尽在主页!
    Scala专栏(spark必学语言 已完结)
    JavaWeb专栏(从入门到实战超详细!!!)
    SSM专栏 (更新中…)
    ​📖​ 本期文章:Mybatis(1)—— 快速入门使用持久层框架Mybatis


    如果对您有帮助还请三连支持,定会一 一回访!🙋🏻‍♂️


    在这里插入图片描述

    一、Mybatis简介

    1.1、原始jdbc操作

    使用·原是jdbc的方式查询数据

    public class SelectData {
        public static void main(String[] args) {
    
            try {
                // 1、注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                // 2、获得连接
                Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/study", "root", "123456");
                // 3、获得satement
                Statement statement = connection.createStatement();
                // 4、定义sql
                String sql = "select * from user";
                // 5、之心sql
                ResultSet resultSet = statement.executeQuery(sql);
                // 6、遍历结果集
                while (resultSet.next()){
                    int id = resultSet.getInt(1);
                    String name = resultSet.getString(2);
                    String passwd = resultSet.getString(3);
                    System.out.println(id + "---" + name +"---" + passwd);
                }
                // 7、释放资源
                resultSet.close();
                statement.close();
                connection.close();
    
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    1.2、原始jdbc操作的缺点

    原始jdbc开发存在的问题如下:

    ①数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能

    ②sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变java代码。

    ③查询操作时,需要手动将结果集中的数据手动封装到实体中。插入操作时,需要手动将实体的数据设置到sql语句的占位符位置

    应对上述问题给出的解决方案:

    使用数据库连接池初始化连接资源

    将sql语句抽取到xml配置文件中

    使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射

    1.3、Mybatis是什么?

        mybatis 是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。

    mybatis通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句。

    最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作。

    Mybatis官网地址:http://www.mybatis.org/mybatis-3/

    在这里插入图片描述

    二、Mybatis的快速入门

    开发步骤:

    ①添加MyBatis的坐标

    ②创建user数据表

    ③编写User实体类

    ④编写映射文件UserMapper.xml

    ⑤编写核心文件SqlMapConfig.xml

    ⑥编写测试类

    1、环境准备

    创建一个新的module。导入相应的依赖坐标

    <dependencies>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.37version>
        dependency>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.4.6version>
        dependency>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
        dependency>
        
        <dependency>
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
            <version>1.2.17version>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2、创建一张表

    在这里插入图片描述

    3、创建实体类

    public class User {
        private int id; // 用户id
        private String username; // 用户名
        private String password; // 密码
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    4、编写UserMapper映射文件

    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="userMapper">
        <select id="findAll" resultType="com.zhou.mybatis.domain.User">
            select * from user 
        select>
        
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5、编写mybatis核心配置文件

    
    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">transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/study"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
     
        <mappers>
            <mapper resource="com/zhou/mybatis/mapper/UserMapper.xml">mapper>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    6、编写测试代码

    public class MybatisTest {
    
        @Test
        public void test1() throws IOException {
            // 1、加载核心配置文件
            InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
            // 2、获得session工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            // 3、获得session会话对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 4、执行操作 参数就是 namespace + id
            List<User> userList = sqlSession.selectList("userMapper.findAll");
            // 5、打印数据
            System.out.println(userList);
            // 6、释放资源
            sqlSession.close();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    7、测试

    在这里插入图片描述

    三、mybatis映射文件概述

    在这里插入图片描述

    3.1、mybatis插入数据操作

    1、编写UserMapper映射文件

    <mapper namespace="userMapper">
        
        <select id="findAll" resultType="com.zhou.mybatis.domain.User">
            select *
            from user
        select>
    
        
        <insert id="addUser" parameterType="com.zhou.mybatis.domain.User">
            insert into user
            values (#{id}, #{usernaame}, #{password})
        insert>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2、编写测试代码

    @Test // 插入操作
    public void test2() throws IOException {
        // 模拟user对象
        User user = new User();
        user.setId(3);
        user.setUsername("张无忌");
        user.setPassword("123");
    
        // 1、加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2、获取session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        // 3、获得session会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 4、执行操作
        sqlSession.insert("userMapper.addUser",user);
        // 5、释放资源
    	sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3、测试

    在这里插入图片描述

    在这里插入图片描述

    这是由于mybatis默认是不提交事务的,当你进行增删改操作的时候,需要手动提交事务

    在这里插入图片描述

    在这里插入图片描述

    插入操作需要注意的问题

    • 插入语句使用insert标签

    • 在映射文件中使用parameterType属性指定要插入的数据类型

    •Sql语句中使用#{实体属性名}方式引用实体中的属性值

    •插入操作使用的API是sqlSession.insert(“命名空间.id”,实体对象);

    •插入操作涉及数据库数据变化,所以要使用sqlSession对象显示的提交事务,即sqlSession.commit()

    3.2、mybatis的修改数据操作

    1、编写UserMapper映射文件

    
    <update id="updateUser" parameterType="com.zhou.mybatis.domain.User">
        update user
        set username=#{username},
            password=#{password}
        where id = #{id}
    update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2、编写测试代码

    @Test // 修改操作
    public void test3() throws IOException {
        // 模拟user对象
        User user = new User();
        user.setId(3);
        user.setUsername("孙悟空");
        user.setPassword("000");
    
        // 1、加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2、获取session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        // 3、获得session会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 4、执行操作
        sqlSession.update("userMapper.updateUser",user);
    
        // TODO 注意 mybatis在执行更新操作的时候 需要提交事务
        sqlSession.commit();
    
        // 5、释放资源
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3、测试

    在这里插入图片描述

    更新操作注意的问题:

    • 修改语句使用update标签

    • 修改操作使用的API是sqlSession.update(“命名空间.id”,实体对象);

    3.3、mybatis的删除数据操作

    1、编写UserMapper映射文件

    在这里插入图片描述

    2、编写测试代码

    @Test // 删除操作
    public void test4() throws IOException {
    
        // 1、加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2、获取session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        // 3、获得session会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 4、执行操作
        sqlSession.delete("userMapper.deleteUser",3);
    
        // TODO 注意 mybatis在执行更新操作的时候 需要提交事务
        sqlSession.commit();
    
        // 5、释放资源
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3、测试

    在这里插入图片描述

    删除操作注意问题;

    • 删除语句使用delete标签

    •Sql语句中使用#{任意字符串}方式引用传递的单个参数

    •删除操作使用的API是sqlSession.delete(“命名空间.id”,Object);

    3.4、知识小结

    增删改查映射配置与API:

    查询数据: List<User> userList = sqlSession.selectList("userMapper.findAll");
        <select id="findAll" resultType="com.itheima.domain.User">
            select * from User
        select>
    添加数据: sqlSession.insert("userMapper.add", user);
        <insert id="add" parameterType="com.itheima.domain.User">
            insert into user values(#{id},#{username},#{password})
        insert>
    修改数据: sqlSession.update("userMapper.update", user);
        <update id="update" parameterType="com.itheima.domain.User">
            update user set username=#{username},password=#{password} where id=#{id}
        update>
    删除数据:sqlSession.delete("userMapper.delete",3);
        <delete id="delete" parameterType="java.lang.Integer">
            delete from user where id=#{id}
        delete>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    四、mybatis核心配置文件概述

    4.1、mybatis核心配置文件层级关系

    在这里插入图片描述

    4.2、mybatis常用配置解析

    4.2.1、environments标签

    数据库环境的配置,支持多环境配置

    在这里插入图片描述

    其中,**事务管理器(transactionManager)**类型有两种:

    •JDBC:这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。

    •MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。

    其中,数据源(dataSource)类型有三种:

    •UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。

    •POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。

    •JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。

    4.2.2、mapper标签

    该标签的作用是加载映射文件的,加载方式有如下几种:

    1、使用相对于类路径的资源引用,例如:

    2、使用完全限定资源定位符(URL),例如:

    3、使用映射器接口实现类的完全限定类名,例如:

    4、将包内的映射器接口实现全部注册为映射器,包扫描,例如:

    4.2.3、Properties标签

    实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载外部配置的properties文件

    比如我们将数据源信息抽取到外部文件中;

    在这里插入图片描述

    在这里插入图片描述

    4.2.4、typeAliases标签

    在这里插入图片描述

    自定义别名:

    在mybatis核心配置文件中自定义别名

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    上面我们是自定义的别名,mybatis框架已经为我们设置好的一些常用的类型的别名

    在这里插入图片描述

    在这里插入图片描述

    4.2.5、知识小结

    properties标签:该标签可以加载外部的properties文件

    <properties resource="jdbc.properties">properties>
    
    • 1

    typeAliases标签:设置类型别名

    <typeAlias type="com.itheima.domain.User" alias="user">typeAlias>
    
    • 1

    mappers标签:加载映射配置

    <mapper resource="com/itheima/mapper/UserMapping.xml">mapper>
    
    • 1

    environments标签:数据源环境配置标签

    在这里插入图片描述

    五、mybatis相应的API

    5.1、SqlSession工厂构建起SqlSessionFactoryBuilder

    常用API:SqlSessionFactory build(InputStream inputStream)

    通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象

    String resource = "org/mybatis/builder/mybatis-config.xml"; 
    InputStream inputStream = Resources.getResourceAsStream(resource); 
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 
    SqlSessionFactory factory = builder.build(inputStream);
    
    • 1
    • 2
    • 3
    • 4

    其中, Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、文件系统或一个 web URL 中加载资源文件。

    6.2 SqlSession工厂对象SqlSessionFactory

    SqlSessionFactory 有多个个方法创建SqlSession 实例。常用的有如下两个:

    在这里插入图片描述

    6.3 SqlSession会话对象

    SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到·所有执行语句、提交或回滚事务和获取映射器实例的方法。

    执行语句的方法主要有:

    <T> T selectOne(String statement, Object parameter)  // 查询一个
    <E> List<E> selectList(String statement, Object parameter)  // 查询所有
    int insert(String statement, Object parameter) // 添加数据 
    int update(String statement, Object parameter) // 修改数据
    int delete(String statement, Object parameter) // 删除数据
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    操作事务的方法主要有:

    void commit()   // 提交事务
    void rollback()  // 回滚事务
    
    • 1
    • 2

    六、Mybatis的Dao层实现

    6.1、传统开发方式

    新建一个module

    依赖坐标:

    <dependencies>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.37version>
        dependency>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.4.6version>
        dependency>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
        dependency>
        
        <dependency>
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
            <version>1.2.17version>
        dependency>
    
    dependencies>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    编写好User实体,编写好UserMapper映射文件

    编写好mybatis核心配置文件

    1、编写UserMapper接口

    public interface UserMapper {
        
        public List<User> findAll();
    }
    
    • 1
    • 2
    • 3
    • 4

    2、编写UserMapper实现类

    public class UserMapperImpl implements UserMapper {
        public List<User> findAll() throws IOException {
            // 1、加载mybatis核心配置文件
            InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
            // 2、获取sqlsessionFactory工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            // 3、获取session会话对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 4、执行操作
            List<User> userList = sqlSession.selectList("userMapper.findAll");
            // 5、释放资源
            sqlSession.close();
            // 6、返回查询结果
            return userList;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3、测试传统方式

    public class UserService {
        public static void main(String[] args) throws IOException {
    
            // 创建dao层对象 当前dao层实现是手动实现的
            UserMapper userMapper = new UserMapperImpl();
    
            List<User> all = userMapper.findAll();
            System.out.println(all);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    传统开发方式需要自己手动创建实现类

    6.2、代理开发方式

    什么是代理开发方式?

    采用 Mybatis 的代理开发方式实现 DAO 层的开发,这种方式是我们后面进入企业的主流。

    Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法

    Mapper 接口开发需要遵循以下规范:

    1、Mapper.xml文件中的namespace与mapper接口的全限定名相同

    2、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

    3、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同

    4、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

    在这里插入图片描述

    实践:
    在这里插入图片描述

    编写测试代码:

    public class UserService {
        public static void main(String[] args) throws IOException {
    
            InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            List<User> userList = mapper.findAll();
            System.out.println(userList);
    
            User user = mapper.findById(1);
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.3、知识小结

    mybatis的dao层实现有两种方式:

    1、传统开发方式 手动实现

    2、代理方式 自动生成代理对象

    七、mybatis映射文件深入

    7.1、动态sql

    Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。

    在这里插入图片描述

    7.2、开发环境搭建

    1、新建一个模块

    2、导入依赖坐标

    在这里插入图片描述

    3、编写实体类User

    4、编写UserMapper映射文件

    5、编写sqlMapConfig mybatis的核心配置文件

    6、编写测试类进行测试。

    7、导入log4j.properties文件,将消息级别改为debug可以看到日志打印中的sql语句

    在这里插入图片描述

    7.3、动态Sql之if

    我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

    
    <select id="findByCondition" parameterType="user" resultType="user">
        select * from user where 1=1
        <if test="id!=0">
            and id=#{id}
        if>
        <if test="username!=null">
            and username=#{username}
        if>
        <if test="password!=null">
            and password=#{password}
        if>
    
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    我们可以不用自己写where 1 = 1,mybatis提供了一个where标签 作用和where1=1一样

        
        <select id="findByCondition" parameterType="user" resultType="user">
    
            select * from user
            <where>
                <if test="id!=0">
                    and id=#{id}
                if>
                <if test="username!=null">
                    and username=#{username}
                if>
                <if test="password!=null">
                    and password=#{password}
                if>
            where>
    
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    7.4、动态Sql之foreach

    在实际中比如我们有这样的需求该如何实现?

    在这里插入图片描述

    循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN(1,2,3);

    
    <select id="findByIds" parameterType="list" resultType="user">
        select * from user
        <where>
            <foreach collection="list" open="id in(" close=")" item="id" separator=",">
                #{id}
            foreach>
        where>
    
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试代码

    @Test
    public void test2() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
    
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        // 模拟ids数据
        ArrayList<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
    
        List<User> userListByIds = mapper.findByIds(ids);
    
        System.out.println(userListByIds);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    查询结果:

    在这里插入图片描述

    foreach标签的属性的具体含义如下:

    •collection:代表要遍历的集合元素,注意编写时不要写#{}

    •open:代表语句的开始部分

    •close:代表结束部分

    •item:代表遍历集合的每个元素,生成的变量名

    •sperator:代表分隔符

    7.5、Sql片段的抽取

    Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的

    
    <sql id="selectUser">
        select *
        from user
    sql>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    <select id="findByIds" parameterType="list" resultType="user">
        -- select * from user
        -- 采用抽取的sql片段
        <include refid="selectUser">include>
        <where>
            <foreach collection="list" open="id in(" close=")" item="id" separator=",">
                #{id}
            foreach>
        where>
    
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    7.6、知识小结

    mybatis映射文件配置:

    标签作用
    查询
    插入
    修改
    删除
    where条件 相当于where1=1
    判断 拼接sql
    循环拼接sql
    sql片段抽取 提高复用性

    八、mybatis核心配置文件深入

    8.1、typeHandlers

    无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器(截取部分)。

    在这里插入图片描述

    但是有些数据类型不支持的时候,就需要我们自定义类型转换器

    你可以重写类型处理器或创建自己的类型处理器来处理不支持的数据类型或者非标准的类型

    具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个JDBC类型。

    例如需求:一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成java的Date,即java的Date与数据库的varchar毫秒值之间转换。

    开发步骤:

    ①定义转换类继承类BaseTypeHandler

    ②覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时 mysql的字符串类型转换成 java的Type类型的方法

    ③在MyBatis核心配置文件中进行注册

    具体我们来编码看看:

    1、准备环境

    【1】建表

    创建一张user表 生日字段存储毫秒值

    在这里插入图片描述

    【2】编写实体类User

    package com.zhou.config.domain;
    
    import java.util.Date;
    
    public class User {
        private int id;
        private String username;
        private String password;
        private Date birthday;
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    【3】编写mapper接口的方法

    public interface UserMapper {
    
        public void addUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4

    2、编写自定义类型处理器

    package com.zhou.config.handler;
    
    import org.apache.ibatis.type.BaseTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Date;
    
    // 继承BaseTypeHandler类并制定要转换的类型
    public class MyDateTypeHandler extends BaseTypeHandler<Date> {
        // 将java类型转为数据库所需要的类型
        public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
            long time = date.getTime(); // getTime()方法获取毫秒值
            preparedStatement.setLong(i,time);
        }
    
        // 将数据库中的类型转为java类型
    
        /** 根据字段名称转换
         * @param resultSet 查询结果集
         * @param s  要转换的字段名称
         * @return 返回转换后的日期
         * @throws SQLException
         */
        public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
            // 获取结果集中的我们所需要的数据 转为Date类型 返回
            long time = resultSet.getLong(s);
            Date date = new Date(time);
            return date;
        }
    
        // 将数据库中的类型转为java类型
    
        /**
         * 根据字段位置转换
         * @param resultSet 查询结果集
         * @param i 字段所在的索引位置
         * @return 返回的转换后的日期
         * @throws SQLException
         */
        public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
            long aLong = resultSet.getLong(i);
            Date date = new Date(aLong);
            return date;
        }
    
        // 将数据库中的类型转为java类型
        public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
            long aLong = callableStatement.getLong(i);
            Date date = new Date(aLong);
            return date;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    3、注册类型处理器

    
    <typeHandlers>
        <typeHandler handler="com.zhou.config.handler.MyDateTypeHandler">typeHandler>
    typeHandlers>
    
    • 1
    • 2
    • 3
    • 4

    8.2、plugins

    MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据

    ①导入通用PageHelper的坐标

    ②在mybatis核心配置文件中配置PageHelper插件

    ③测试分页数据获取

    1、导入坐标

    
    <dependency>
        <groupId>com.github.pagehelpergroupId>
        <artifactId>pagehelperartifactId>
        <version>3.7.5version>
    dependency>
    <dependency>
        <groupId>com.github.jsqlparsergroupId>
        <artifactId>jsqlparserartifactId>
        <version>0.9.1version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2、在mybatis核心配置文件中配置分页助手插件

    
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            
            <property name="dialect" value="mysql"/>
        plugin>
    plugins>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、测试

    我们只需要在查询全部前面加上分页相关参数 即可

    @Test
    public void test1() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        // 设置分页相关参数 当前页 + 每页显示条数
        PageHelper.startPage(1,3);
    
        List<User> userList = mapper.findAll();
        for (User user : userList) {
            System.out.println(user);
        }
    
        System.out.println(userList);
        sqlSession.close();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    从第一页开始 每页显示3条数据

    在这里插入图片描述

    获得分页相关的其他参数

    System.out.println("----------------------- 获取其他相关参数 ----------------------------");
    
    // 获得分页其他相关参数
    PageInfo<User> userPageInfo = new PageInfo<User>(userList);
    System.out.println("当前页:" + userPageInfo.getPageNum());
    System.out.println("每页显示条数:" + userPageInfo.getPageSize());
    System.out.println("总条数:" + userPageInfo.getTotal());
    System.out.println("总页数:" + userPageInfo.getPages());
    System.out.println("上一页:" + userPageInfo.getPrePage());
    System.out.println("下一页:" + userPageInfo.getNextPage());
    System.out.println("是否第一页:" + userPageInfo.isIsFirstPage());
    System.out.println("是否最后一页:" + userPageInfo.isIsLastPage());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    8.3、知识小结

    mybatis核心配置文件常用标签:

    1、properties标签:该标签可以加载外部的properties文件

    2、typeAliases标签:设置类型别名

    3、environments标签:数据源环境配置标签

    4、typeHandlers标签:配置自定义类型处理器

    5、plugins标签:配置MyBatis的插件

    6、settings标签:开启延迟加载、将表中字段的下划线自动转为驼峰功能等

    在这里插入图片描述

    九、mybatis开发小细节

    9.1、IDEA开发mybatis模板设置

    我们在IDEA中开发的时候,需要从其他地方比如官网copymybatis的约束头下来 显得比较繁琐,我们可以直接将mybatis的一些通用配置设置为模板,通过模板创建即可。

    9.1.1、核心配置文件模板

    首先我们看看哪些是通用的设置:

    
    DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        
        <properties resource="jdbc.properties">properties>
    
    
        
        <typeAliases>
            
    
            
            <package name="com.zhou.config.domain"/>
        typeAliases>
    
    
        
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC">transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                dataSource>
            environment>
        environments>
    
        
        <mappers>
            <mapper resource="com/zhou/config/mapper/UserMapper.xml">mapper>
        mappers>
    
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    我们就以上述配置为模板

    在这里插入图片描述

    点击+号 新建一个模板

    在这里插入图片描述

    点击 apply 点击ok 退出,测试

    在这里插入图片描述

    在这里插入图片描述

    9.1.2、mapper映射文件模板

    同样先看看哪些是固定的配置

    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="">
    
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    相同的操作步骤,将上述配置copy进去即可

    在这里插入图片描述

    测试:

    在这里插入图片描述

    9.2、封装SqlSessionUtils工具类

    在之前所有的开发测试中我们都需要获取sqlsession对象,具有大量重复的代码需要我们编写,所以我们可以将获取sqlsession对象的代码单独抽取出来封装成一个工具类

    package com.zhou.config.utils;
    
    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 SqlSessionUtils {
    
        public static SqlSession getSqlSession() {
            SqlSession sqlSession = null; // 防止空指针异常
            try {
                // 读取mybatis核心配置文件
                InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
                // 获取SqlSessionFactory对象
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
                // 通过SqlSessionFactory对象打开一个SQLSession
                sqlSession = sqlSessionFactory.openSession(true); // 自动提交事务
            } catch (IOException e) {
                e.printStackTrace();
            }
            return sqlSession;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    测试工具类:

    @Test
    public void test3(){
        // 通过工具类获取SqlSession对象
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        List<User> users = mapper.findAll();
    
        for (User user : users) {
            System.out.println(user);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    9.3、mybatis获取参数的两种方式

    ${} 本质就是字符串拼接

    #{} 本质就是占位符赋值

    第一种情况:当mapper传递过来的参数只有一个参数的时候

    ​ 可以通过${}和#{} 以任意的名称获取参数值,但是要注意

    ​ ${}的单引号问题

    第二种情况:当mapper传递过来的参数有多个的时候

    User findByUsernameAndPassword(String username,String password);
    
    • 1

    此时mybatis会将这些参数放在一个map集合中,以两种方式进行存储

    一种是arg0 、arg1分别表示第一个参数和第二个参数

    select * from user1 where username='${arg0}' and password='${arg1}'
    
    • 1

    另一种就是param1、param2分别表示第一个参数和第二个参数

    select * from user1 where username='${param1}' and password='${param2}'
    
    • 1

    可以通过#{} 也可以通过${}来获取参数

    但是需要注意${}的引号问题

    第三种情况:若mapper接口中方法的参数为多个的时候,我们可以手动将这些参数放在一个map集合最终存储

    只需要通过#{} 或者${}通过我们自己定义的键去获取即可,接下来演示以下:

    【1】首先编写一个方法

    User loginByMap(Map<String,Object> map);
    
    • 1

    【2】再编写测代码

    @Test
    public void test6(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        Map<String,Object> map = new HashMap<>();
        map.put("username","张天爱");
        map.put("password","123");
    
        User user = mapper.loginByMap(map);
        System.out.println(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    【3】编写mapper映射文件

    <select id="loginByMap" resultType="user">
        select * from user1 where username = #{username} and password = #{password}
    select>
    
    • 1
    • 2
    • 3

    这里username就是我们在map中自定义的键

    【4】测试

    在这里插入图片描述

    第四种情况:mapper接口的参数是实体类型的时候

    实体类型以属性名进行访问 需要我们标注参数类型parameterType

    public void addUser(User user);
    
    • 1

    第五种情况:使用@Param注解来命名参数
    此时mybatis会自动将参数放在一个map集合中,以两种方式存储
    第一种 以@Param注解为键,参数为值
    第二种 以param1、param2为键 参数为值

    User loginByParam(@Param("username") String username, @Param("password") String password);
    
    • 1
    <select id="loginByParam" resultType="user">
        select * from user1 where username = #{username} and password = #{password}
    select>
    
    • 1
    • 2
    • 3
    @Test
    public void test7(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        
        User user = mapper.loginByParam("张天爱","123");
        System.out.println(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

  • 相关阅读:
    全国大学生数学竞赛(非数学专业)习题精讲等相关资源
    嵌入式分享合集90
    已解决:KeyError: ‘The truth value of a Series is ambiguous‘ 问题
    web前端JS基础------制作一个获取验证码
    李宇航
    Java并发-操作系统,进程,线程,并行并发?
    分库分表系列:分库分表的前世今生
    ASON 技术简介
    双十一来临,你的WMS仓库管理软件能顶住压力吗
    五种方式实现 Java 单例模式
  • 原文地址:https://blog.csdn.net/m0_66947873/article/details/126032529