Mybatis的了解和学习

Mybatis

框架介绍

框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们个性化的需求。

ORM介绍

ORM(Object Relational Mapping):对象关系映射

指的是持久化数据和实体对象的映射模式,为了解决面向对象与关系型数据库存在的互不匹配的现象的技术。

即数据库中的数据可以读取到java类中保存,也可以将java类中包含的数据存到数据库中

Mabatis介绍

之前学的JDBC可以满足我们对数据库操作的需求,但存在一些问题

  1. 频繁创建和销毁数据库连接会造成系统资源浪费从而影响系统性能
  2. sql语句在代码中硬编码(写死),如果要修改sql语句,就需要修改java代码,造成代码不易维护。
  3. 查询操作时需要手动将结果集中的数据封装到实体对象中。
  4. 增删改查操作需要参数时,需要手动将实体对象的数据设置到sql语句的占位符。

解决方案

  1. 使用数据库连接池初始化资源
  2. 将sql语句抽取到配置文件中,将来只需要修改配置文件即可
  3. 使用反射,内省等底层技术。将实体与表进行属性与字段的自动映射

也就是说我们存在的问题都是可以解决的,但是我们自己解决起来较为困难,于是我们需要一些别人编写的优秀的框架。

  • Mybatis是一个优秀的基于java的持久层框架,它内部封装了JDBC,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动,创建连接,创建执行者等复杂的操作。
  • Mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中动态参数进行映射生成最终要执行的sql语句。
  • Mybatis执行完sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对JDBC进行了封装,屏蔽了JDBC API底层访问细节,使我们不用与JDBC API打交道,就可以完成对数据库的持久化操作。
  • Mybatis官网:http://www.mybatis.org/mybatis-3/

Mybatis入门程序

通过简单的Mybatis获取数据库数据

  1. 数据准备

    新建一个java项目,在com.luxoin.object下创建User类,在com.luxoin.dao下创建UserTest01类。

    /**
     * @author: luoxin
     * @create: 2021-07-17 19:08
     **/
    
    package com.luxoin.object;
    
    public class User {
          
          
    
        private int id,age;
        private String name;
    
        public User(int id, int age, String name) {
          
          
            this.id = id;
            this.age = age;
            this.name = name;
        }
    
        public User() {
          
          
        }
    
        @Override
        public String toString() {
          
          
            return "User{" +
                    "id=" + id +
                    ", age=" + age +
                    ", name='" + name + '\'' +
                    '}';
        }
    
        public int getId() {
          
          
            return id;
        }
    
        public void setId(int id) {
          
          
            this.id = id;
        }
    
        public int getAge() {
          
          
            return age;
        }
    
        public void setAge(int age) {
          
          
            this.age = age;
        }
    
        public String getName() {
          
          
            return name;
        }
    
        public void setName(String name) {
          
          
            this.name = name;
        }
    
        public static void main(String[] args) {
          
          
    
        }
    }
    
    
    /**
     * @author: luoxin
     * @create: 2021-07-17 19:10
     **/
    
    package com.luxoin.dao;
    
    import com.luxoin.object.User;
    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 org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class UserTest01 {
          
          
    
        public static void main(String[] args) {
          
          
    
        }
        @Test
        public void selectAll() throws IOException {
          
          
    //        1.加载核心配置文件
            InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
    //        2.获取sqlSession工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    //        3.通过sqlSession工厂获取sqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    //        4.执行映射配置文件中的sql语句,并接收结果
            List<User> list = sqlSession.selectList("UserMapper.selectAll");
    //        5.处理结果
            for(User u : list) {
          
          
                System.out.println(u);
            }
    //        6.释放资源
            sqlSession.close();
            is.close();
        }
    }
    
    
  2. 导入jar包

    链接:https://pan.baidu.com/s/1iBL6ghrzJp9-aoVPtwEFSA
    提取码:4r4r

    导包步骤为在项目根目录下创建一个名为libs的目录,将相关jar包复制到目录下,然后选中他们并右击,点击Add As Library

  3. 在src下创建映射配置文件UserTest01.xml(如果是javaweb项目则文件位置为resource目录下)

    <?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="UserMapper">
        <select id="selectAll" resultType="com.luxoin.object.User">
            select * from user;
        </select>
    </mapper>
    
  4. 在src下创建核心配置文件MybatisConfig.xml(如果是javaweb项目则文件位置为resource目录下)

    <?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="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"></transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://127.0.0.1:3306/test01"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="UserTest01.xml"/>
        </mappers>
    </configuration>
    
  5. 编写测试类完成相关API的使用

可以在主函数中调用编写的函数,也可以直接双击函数名运行函数(必须有@Test注解,相关jar包已经在上面给出)。

快速入门小结

  1. 框架

    框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们个性化的需求。

  2. ORM

    对象关系映射,数据和实体对象的映射

  3. Mybatis

    是一个优秀的基于java的持久层框架,它内部封装了JDBC

  4. 入门步骤

    1. 导入jar包
    2. 编写映射配置文件
    3. 编写核心配置文件
    4. 使用相关API完成编程

Mybatis相关API

Resources

org.apache.ibatis.io.Resources:加载资源的工具类(ibatis是mybatis的前生)

核心方法:

返回值 方法名 说明
InputStream getResourceAsStream(String fileName) 通过类加载器返回指定资源的字节输入流

SqlSessionFactoryBuilder

org.apache.ibatis.session.SqlSessionFactoryBuilder:获取SqlSessionFactory工厂对象的功能类。

返回值 方法名 说明
SqlSessionFactory build(InputStream is) 通过指定字节资源输入流获取SqlSession工厂对象

SqlSessionFactory

org.apache.ibatis.session.SqlSessionFactory:获取SqlSession构建者对象的工厂接口

返回值 方法名 说明
SqlSession openSession() 获取SqlSession构建者对象,并开启手动提交事务
SqlSession openSession(boolean autoCommit) 获取SqlSession构建者对象,如果参数为true,则开启自动提交事务

SqlSession

org.apache.ibatis.session.SqlSession:构建者对象接口。用于执行SQL,管理事务,接口代理。

返回值 方法名 说明
List selectList(String statement, Object parameter) 执行查询语句,返回List集合
T selectOne(String statement, Object parameter) 执行查询语句,返回一个结果对象
int insert(String statement, Object parameter) 执行insert语句,返回影响行数
int updata(String statement, Object parameter) 执行updata语句,返回影响行数
int delete(String statement, Object parameter) 执行delete语句,返回影响行数
void commit() 提价事务
void rollback() 回滚事务
T getMapper(Class cls) 获取指定接口的代理实现类对象
void close() 释放资源

Mybatis映射配置文件

映射配置文件介绍

映射配置文件包含了数据和对象之间的映射关系以及要执行的sql语句。

映射配置文件大致可分为3个部分

<?xml version="1.0" encoding="utf-8" ?>
<!--
    上面一定要顶格写
    说明了xml的版本和编码
-->

<!--
    Mybatis的DTD的约束,作用是作用是建议书写格式是否正确以及给予提示和自动补全
-->
<!DOCTYPE mapper
        PUBLIC  "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--
    mapper   核心根标签
    namespace属性:名称空间,通过该属性找到对应映射
-->
<mapper namespace="UserMapper">
<!--
    select标签:表查询功能的标签
    id属性:唯一标识,配合namespace找到要执行的sql语句
    resultType属性:指定查询结果要映射的对象
    parameterType属性:指定参数映射对象的类型    例如java.lang.Long
-->
    <select id="selectAll" resultType="com.luxoin.object.User">
        select * from user;
    </select>
</mapper>

实现了增删查改各个功能后的文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<!--
    上面一定要顶格写
    说明了xml的版本和编码
-->

<!--
    Mybatis的DTD的约束,作用是作用是建议书写格式是否正确以及给予提示和自动补全
-->
<!DOCTYPE mapper
        PUBLIC  "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--
    mapper   核心根标签
    namespace属性:名称空间,通过该属性找到对应映射
-->
<mapper namespace="UserMapper">
<!--
    select标签:表查询功能的标签
    id属性:唯一标识,配合namespace找到要执行的sql语句
    resultType属性:指定查询结果要映射的对象
    parameterType属性:指定参数映射对象的类型    例如java.lang.Long
-->
    <select id="selectAll" resultType="com.luxoin.object.User">
        select * from user;
    </select>
    <select id="selectById" resultType="com.luxoin.object.User" parameterType="java.lang.Integer">
        select * from user where id = #{id};
    </select>
    <insert id="insert" parameterType="com.luxoin.object.User">
        insert into user values(#{id},#{name},#{age});
    </insert>
    <update id="update" parameterType="com.luxoin.object.User">
        update user set name = #{name} where id = #{id};
    </update>
    <delete id="delete" parameterType="java.lang.Integer">
        delete from user where id = #{id};
    </delete>
</mapper>
/**
 * @author: luoxin
 * @create: 2021-07-17 19:10
 **/

package com.luxoin.dao;

import com.luxoin.object.User;
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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UserTest01 {
    
    

    public static void main(String[] args) throws IOException {
    
    

    }
    @Test
    public void delete() throws IOException {
    
    
        InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        int result = sqlSession.delete("UserMapper.delete", 4);
        sqlSession.commit();
        System.out.println("影响了"+result+"行");
        sqlSession.close();
        is.close();

    }
    @Test
    public void update() throws IOException {
    
    
        InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = new User(1,45,"罗新");
        int result = sqlSession.update("UserMapper.update", user);
        sqlSession.commit();
        System.out.println("影响了"+result+"行");
        sqlSession.close();
        is.close();
    }
    @Test
    public void insert() throws IOException {
    
    
//        1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
//        2.获取sqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//        3.通过sqlSession工厂获取sqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
//        4.执行映射配置文件中的sql语句,并接收结果
        User user = new User(5,64,"赵六");
        int result = sqlSession.insert("UserMapper.insert", user);
        sqlSession.commit();
//        5.处理结果
        System.out.println("影响了"+result+"行");
//        6.释放资源
        sqlSession.close();
        is.close();

    }
    @Test
    public void selectById() throws IOException {
    
    
//        1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
//        2.获取sqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//        3.通过sqlSession工厂获取sqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
//        4.执行映射配置文件中的sql语句,并接收结果
        User s = sqlSession.selectOne("UserMapper.selectById",3);
//        5.处理结果
        System.out.println(s);
//        6.释放资源
        sqlSession.close();
        is.close();
    }
    @Test
    public void selectAll() throws IOException {
    
    
//        1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
//        2.获取sqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//        3.通过sqlSession工厂获取sqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
//        4.执行映射配置文件中的sql语句,并接收结果
        List<User> list = sqlSession.selectList("UserMapper.selectAll");
//        5.处理结果
        for(User u : list) {
    
    
            System.out.println(u);
        }
//        6.释放资源
        sqlSession.close();
        is.close();
    }
}

Mybatis核心配置文件

核心配置文件介绍

核心配置文件包含了Mybatis最核心的设置和属性信息。如数据库的连接,事务,连接池信息等。

<?xml version="1.0" encoding="UTF-8" ?>
<!--文档声明,必须在首行-->
<!--Mybatis的DTD约束-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<!--configuration核心根标签-->
<configuration>
<!--
    environments配置数据库环境,环境可以有多个
    defualt属性指定我们使用的是哪一个环境
-->
    <environments default="mysql">
<!--
    environment标签配置数据库环境
    id属性唯一标识   用于区分不同环境
-->
        <environment id="mysql">
<!--
    transactionManager标签 :事务管理
    type属性:采用JDBC默认的事务处理
-->
            <transactionManager type="JDBC"></transactionManager>
<!--
    dataSource标签:数据源信息
    type属性:连接池
-->
            <dataSource type="POOLED">
<!--
    property标签:配置标签
-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/test01"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>


<!--
    mappers标签:引入映射配置文件
-->
    <mappers>
<!--
    mapper标签:引入指定的映射配置文件
    resource属性指定映射配置文件的路径和名称
-->
        <mapper resource="UserTest01.xml"/>
    </mappers>
</configuration>

数据库连接配置文件的引入

在上面的核心配置文件中我们的数据库连接信息都是写死的,而在正式的开发中,要求我们把数据库连接信息单独的抽取到一个文件中,我们就需要在核心配置文件中引入该文件。

如果我们把数据库连接信息抽取到jdbc.properties文件中

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test01
username=root
password=123456

我们需要一个properties标签来引入数据库连接配置文件,需要resource属性指定文件路径,通过${键名}来获取文件数据。

修改后的核心配置文件为:

<?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="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <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>
        <mapper resource="UserTest01.xml"/>
    </mappers>
</configuration>

起别名

在前面编写的代码中,resultType和parameterType的值我们总是写一长串,例如com.luxoin.object.User,很麻烦,我们希望只用User来代替这一长串的字符。这时候我们可以使用起别名

  • :起别名的父标签
  • :起别名的子标签
  • 属性
    • type:指定全类名
    • alias:指定别名
  • :为指定包下所有类起别名的子标签,别名就是类名

起别名的操作需要在核心配置文件下进行

<?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>
    
    <typeAliases>
<!--        为指定类起别名-->
        <typeAlias type="com.luxoin.object.User" alias="User"></typeAlias>
<!--        为该包下的所有类起别名-->
        <package name="com.luxoin.object"/>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <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>
        <mapper resource="UserTest01.xml"/>
    </mappers>
</configuration>

Mybatis传统方式实现dao层

dao:Data Access Object

Dao层传统方式实现

分层思想:控制层(controller),业务层(service),持久层(dao)。

调用流程:控制层调用业务层,月完成调用持久层,而持久层和数据库打交道

LOG4J (log for java 4读英文)

在日常开发过程中排查问题时难免需要输出Mybatis真正执行的sql语句,参数,结果等信息,我们就可以借助log4j的功能来实现执行信息的输出。

Mybatis高级

Mybatis接口代理方式实现dao层

接口代理方式-实现规则

​ 传统方式实现dao层,我们既要实现接口,还要写实现类。而Mybatis框架可以帮助我们省略编写dao实现类的步骤,程序员只需要编写接口,由Mybatis框架根据接口的定义来创建该接口的动态代理对象。

实现规则

  1. 映射配置文件中的namespace必须和dao层接口的全类名相同
  2. 映射配置文件中的增删改查标签的id属性必须和dao层接口的方法名相同
  3. 映射配置文件中的增删改查标签的parameterType属性必须和dao层接口方法的参数相同
  4. 映射配置文件中的增删改查标签的resultType属性必须和dao层接口方法的返回值相同

也就是说之前函数的具体实现是在dao层实现类,但现在dao实现类可以省略,所以函数的具体实现变到了service层实现类,且实现方法有了一些改动。

@Override
    public List<User> selectAll() {
    
    
        InputStream is = null;
        List<User> list = null;
        SqlSession sqlSession = null;
        try {
    
    
//        1.加载核心配置文件
            is = Resources.getResourceAsStream("MybatisConfig.xml");
//        2.获取sqlSession工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//        3.通过sqlSession工厂获取sqlSession对象
            sqlSession = sqlSessionFactory.openSession();
//        4.获取UserMapper接口的实现类对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        5.通过实现类对象调用方法,接收结果
            list = mapper.selectAll();
//        5.处理结果
            for (User u : list) {
    
    
                System.out.println(u);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //        6.释放资源
            sqlSession.close();
            try {
    
    
                is.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return list;
    }
   

Mybatis映射配置文件- 动态SQL

动态SQL介绍

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

多条件查询:

当查询条件为3时的SQL语句为:select * from user where id=? andname=? and age=?;

当查询条件为2时的SQL语句为:select * from user where id=? andname=?;

上面的情况如果用之前的知识的话只能写两个不同的select标签,写成两个函数,但是在动态SQL中只需要一条SQL语句够了。

动态SQL标签

:条件标签。如果有动态条件,则使用该标签代替where关键字

:条件判断标签

下面的配置文件实现了多条件查询,应该能很轻松读懂,但必须有id才能查询

<select id="selectByIds" resultType="com.luxoin.object.User" parameterType="java.lang.Integer">
        select * from user
        <where>
            <if test="id != null"> id = #{id}</if>
            <if test="name != null">and name = #{name}</if>
            <if test="age != age">and age = #{age}</if>
        </where>
    </select>

:循环遍历标签

例如下面两条语句:

select * from user where id in (1,2);
select * from user where id in (1,2,3);

我们想要用一条动态SQL语句实现就得用到foreach标签。我们把后面括号中的内容看作是集合中的元素,也就是我们传入一个集合,然后用foreach循环把集合中的元素都放到括号里。

<!--
collection属性:存放参数容器的类型
open属性:开始的sql语句
close属性:结束的sql语句
item:参数变量的名称
separator:各参数之间的分隔符
     -->
<foreach collection="" close="" item="" open="" separator="" >

</foreach>

上述动态sql语句的映射配置文件为:

<select id="selectByIdss" resultType="com.luxoin.object.User" parameterType="java.util.List">
        select * from user
        <where>
        <foreach collection="java.util.List" close=");" item="id" open="id in (" separator="," >
            #{id}
        </foreach>
        </where>
    </select>

SQL片段抽取

  • 我们可以把一些重复性的SQL语句进行抽取,以达到复用的效果。

  • :抽取sql语句标签

    <sql id="片段唯一标识">抽取的sql语句</sql>
    
  • :引入sql片段标签

    <include refid="标识" />
    

Mybatis核心配置文件–分页插件

分页插件介绍

  • 分页可以将很多条结果分页展示
  • 如果当前在第一页,则没有上一页,在最后一页则没有下一页
  • 需要明确当前是第几页,这一页显示多少条结果

在sql中分页查询需要借助limit关键字

​ limit n,m;代表从n号索引开始,查询连续的m条记录

在企业级开发中,分页也是一种常见的技术,但目前使用的Mybatis是不带分页功能的,如果想实现分页功能,需要我们手动编写limit语句,但不同数据库实现分页操作的sql语句不一样,所以手写分页成本较高。这时候可以借助分页插件实现分页功能。

PageHelper:第三方分页助手,将复杂的分页操作进行封装,从而使分页功能变得简单

分页插件实现步骤

  1. 导入jar包

    链接:https://pan.baidu.com/s/1TnjK6_aADf0B-HKR-W_zpw
    提取码:4r4r

  2. 在核心配置文件中集成分页助手插件

    <plugins>
            <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
        </plugins>
    
  3. 在测试类中使用分类助手相关API实现分页功能

其实就是在执行查询之前执行

PageHelper.startPage(1,2);

两个参数分别为pageindex(从1开始),pagesize

这里需要注意的是在编写映射配置文件时不要在语句结尾加 ; ,否则会报错

Mybatis多表操作

多表模型

  • 我们之前学习的都是单表操作的,而实际开发中,随着业务难度的加深,肯定需要多表操作的。
  • 多表模型分类
    • 一对一:在任意一方建立外键,关联对方主键
    • 一对多:在多的一方建立外键,关联一的一方的主键
    • 多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键

一对一

  • 一对一模型:人和身份证

多表查询和单表查询最大的不同在于映射配置文件。多表查询得到的结果不在只是保留到一个实体类中。

<?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.luoxin.table01.OneToOneMapper">
<!--    id为唯一标识符   type为映射类型,这里是别名-->
    <resultMap id="OneToOne" type="card">
<!--        id标签用于主键映射   column属性指定列名   property属性指定类中成员名-->
        <id column="cid" property="id"></id>
<!--        result标签用于非主键映射,column属性指定列名   property属性指定类中成员名-->
        <result column="number" property="number"></result>
<!--
            第三个属性是另一个实体类,需要另一个标签association
            association:用于配置被包含对象的映射关系
            property:被包含对象的变量名
            javaType:被包含对象的数据类型这里是别名
-->
        <association property="p" javaType="person">
            <id column="pid" property="id"></id>
            <result column="name" property="name"></result>
            <result column="age" property="age"></result>
        </association>
    </resultMap>
<!--    之前的resulitType是针对单表,多表需要resultMap,resultMap需要先声明-->
    <select id="selectAll" resultMap="OneToOne">
        SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid = p.id
    </select>
</mapper>

一对多

  • 一对多模型:学生和班级

上面的一对一是在一个对象中包含另一个对象,而一对多则是在一个对象中包含一个集合,集合中充满其他对象。其实也是映射配置文件不同

<?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.luoxin.table02.OneToManyMapper">
    <resultMap id="otm" type="classes">
        <id column="cid" property="id"></id>
        <result column="cname" property="name"></result>

<!--
        collection:配置被包含的集合对象映射关系
-->
        <collection property="student" ofType="student">
            <id column="sid" property="id"></id>
            <result column="sname" property="name"></result>
            <result column="age" property="age"></result>
        </collection>
    </resultMap>
    <select id="selectAll" resultMap="otm">
        SELECT c.id cid,c.name cname,s.id sid,s.name sname,s.age age FROM class c,student s WHERE s.cid=c.id
    </select>
</mapper>

多对多

多对多模型:学生和课程,一个学生可以选多门课程,一个课程也可以被多个学生选择。

三个模型的项目源码以及数据库sql语句:

链接:https://pan.baidu.com/s/16ErMbSDgxWbQ7lfcSGE4lA
提取码:4r4r

Mybatis注解开发

常用注解介绍

我们除了可以使用映射配置文件来操作外,还可以使用注解形式来操作。配置文件太复杂,注解较简单。虽然注解更简洁,但配置文件使用方式我们也应该掌握。

常用注解:

@Select(“查询的sql语句”):执行查询操作注解

@Insert(“新增的sql语句”):执行新增操作注解

@Updata(“修改的sql语句”):执行修改操作注解

@Delete(“删除的sql语句”):执行删除操作注解

注解的使用

  • 创建接口和查询方法

    映射的底层是代理,而代理是需要接口的,所以接口的创建必不可少,在接口中创建我们要使用的方法,如果是之前的话,我们就得编写映射配置文件,在映射配置文件中配置接口位置以及返回值类型以及返回值对应关系。使用注解根本不需要这么复杂,我们只需要在接口的方法声明上写一行@Select(“查询的sql语句”)。刚开始我也有点诧异,难道连返回结果的映射都不需要了吗?

    于是我尝试了

    select name,id,age from user
    select * from user
    select id,name,age from user
    

    这几条顺序不一样的语句,他们的查询结果是一样的,最后三个的输出结果都一样,能正常匹配,也就是说注解里确实有自动封装机制。

    学到后面会发现上面只是具有简单的封装功能,即我们查询到的字段和实体类中属性名相同时才能正确封装,否则不行。后面会学到注解封装。

  • 在核心配置文件中配置映射关系

    配置方法为

    <mappers>
    <package name="接口所在包的路径">
    </mappers>
    

    注意是包的路径,不需要具体到某个类。

  • 编写测试类

    完成上面两步后就可以测试了

注解多表操作

前面学习了注解,但只是单表查询的注解,我们甚至都不需要进行结果封装。接下来学习的多表操作的注解就比较麻烦了。我们需要对查询到的字段进行手动封装。下面的图片就是封装过程。其中的colume 和 property我们都已经很熟悉了,就是把查询到的colume字段封装到类的property属性

  • 一对一实现

    注意:其实在第三个result里面也有自动封装,所以要求我们自定义类的属性名和数据库字段名要相同

    @Select("select * from card")
        //Results里面是多个Result,用大括号圈起来
        @Results({
          
          
                //每个Result代表一项,把查询到的colume字段封装到类的property属性
                @Result(column = "id",property = "id"),
                @Result(column = "number",property = "number"),
                //当有一项是一个自定义对象时使用如下格式
                @Result(
                        //one = @One(select = "com.luoxin.zhujie.zhujie2.selectById")是一对一注解的格式,后面的字符串是我们要调用的另一个函数的路径
                        //我的理解是  把查询到的pid作为参数传入one这个函数中,然后将结果封装到javaType指定类中且起名为 p
                        column = "pid",
                        one = @One(select = "com.luoxin.zhujie.zhujie2.selectById"),
                        javaType = Person.class,
                        property = "p"
                )
        })
        public abstract List<Card> selectAll();
    
    public interface zhujie2 {
          
          
        @Select("select * from person where id = #{id}")
        Person selectById(Integer id);
    }
    

    测试类:

    /**
     * @author: luoxin
     * @create: 2021-07-19 15:17
     **/
    
    package com.luoxin.zhujie;
    
    import com.luoxin.bean.Card;
    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;
    import java.util.List;
    
    public class Test {
          
          
    
        @org.junit.Test
        public void selectAll() throws IOException {
          
          
            InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            zhujie mapper = sqlSession.getMapper(zhujie.class);
            List<Card> list = mapper.selectAll();
            for(Card o:list) {
          
          
                System.out.println(o);
            }
            sqlSession.close();
            is.close();
        }
    }
    
    
  • 一对多实现

    在这里插入图片描述

  • 多对多实现

    在这里插入图片描述

Mybatis构建SQL语句

SQL构建对象介绍

  • 我们之前通过注解开发时,相关SQL语句都是自己直接拼写的,拼写起来较麻烦,且容易出错。
  • Mybatis给我们提供了org.apache.ibatis.idbc.SQL功能类专门用于构建sql语句

这个对象以方法代替关键字
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class Test {

  @org.junit.Test
  public void selectAll() throws IOException {
      InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
      SqlSession sqlSession = sqlSessionFactory.openSession(true);
      zhujie mapper = sqlSession.getMapper(zhujie.class);
      List<Card> list = mapper.selectAll();
      for(Card o:list) {
          System.out.println(o);
      }
      sqlSession.close();
      is.close();
  }

}




- 一对多实现

[外链图片转存中...(img-GJtY9x3B-1626682488574)]

- 多对多实现

[外链图片转存中...(img-gN3vAjYX-1626682488576)]

### Mybatis构建SQL语句

**SQL构建对象介绍**

- 我们之前通过注解开发时,相关SQL语句都是自己直接拼写的,拼写起来较麻烦,且容易出错。
- Mybatis给我们提供了org.apache.ibatis.idbc.SQL功能类专门用于构建sql语句

这个对象以方法代替关键字

猜你喜欢

转载自blog.csdn.net/m0_45972156/article/details/118899989
今日推荐