【JAVA】MyBatis上篇

本文详细介绍了MyBatis作为持久层框架的使用,包括项目配置、Mapper代理开发、核心配置文件解析以及数据库的增删改查操作。通过实例展示了如何创建MyBatis项目,配置数据库连接,编写SQL映射文件,定义Mapper接口,以及如何执行SQL语句。此外,还讨论了动态SQL和条件查询的应用,提供了多条件查询的解决方案。
摘要由CSDN通过智能技术生成

目录

【MyBatis】 

【MyBatis——项目示例】

【Mapper代理开发】

【MyBatis核心配置文件】

【MyBatis实现数据库增删改查】

【利用配置文件完成】

一、准备环境

二、功能实现

1.查询所有数据

2.查看详情

3.条件查询


【MyBatis】 

【概述】

MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发

官网:mybatis – MyBatis 3 | 简介

持久层

  • 负责将数据到保存到数据库的那一层代码
  • JavaEE三层架构:表现层、业务层、持久层

框架

  • 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
  • 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展

【MyBatis——项目示例】

查询User表中的所有数据

  1. 创建user表,添加数据

  2. 创建模块,导入坐标
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>mybatis_demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <dependencies>
            <!--mybatis 依赖-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.5</version>
            </dependency>
            <!--mysql 驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.32</version>
            </dependency>
        </dependencies>
        
    </project>
  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:///自己数据库的表名?useSSL=false"/>
                    <property name="username" value="自己的MySQL用户名"/>
                    <property name="password" value="自己的MySQL密码"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <!--加载sql映射文件-->
            <mapper resource="UserMapper.xml"/>
        </mappers>
    </configuration>
  4. 编写 SQL 映射文件 --> 统一管理sql语句,解决硬编码问题
    <?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">
    <!--
        namespace:名称空间
    -->
    <mapper namespace="test">
        <select id="selectAll" resultType="com.itheima.pojo.User">
            select id,username,password,gender,addr from tb_user;
        </select>
    </mapper>
  5. 定义POJO
    //标准的JavaBean类
    public class User {
        private Integer id;
        private String username;
        private String password;
        private String gender;
        private String address;
    
        public User() {
        }
    
        public User(Integer id, String username, String password, String gender, String address) {
            this.id = id;
            this.username = username;
            this.passwords = passwords;
            this.gender = gender;
            this.address = address;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer 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;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", gender='" + gender + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
  6. 加载核心配置文件,获取 SqlSessionFactory 对象
            //加载核心配置文件,获取 SqlSessionFactory 对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  7. 获取 SqlSession 对象,执行 SQL 语句
            //获取SqlSession对象,执行sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //执行sql
            List<User> users = sqlSession.selectList("test.selectAll");
            System.out.println(users);
  8. 释放资源
            //释放资源
            sqlSession.close();

【Mapper代理开发】

【目的】

  • 解决原生方式中的硬编码
  • 简化后期执行SQL

【步骤】——在上述示例项目中改动

  1. 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下

  2. 设置SQL映射文件的namespace属性为Mapper接口全限定名
    <!--
        namespace:名称空间
    -->
    <mapper namespace="com.itheima.mapper.UserMapper">
        <select id="selectAll" resultType="com.itheima.pojo.User">
            select id,username,password,gender,addr from tb_user;
        </select>
    </mapper>
  3. 在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
    public interface UserMapper {
        List<User> selectAll();
    }
    <select id="selectAll" resultType="com.itheima.pojo.User">
            select id,username,password,gender,addr from tb_user;
    </select>
  4. 通过 SqlSession 的 getMapper方法获取 Mapper接口的代理对象
            //获取SqlSession对象,执行sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            
  5. 调用对应方法完成sql的执行
            //执行sql
            List<User> users = userMapper.selectAll();
            System.out.println(users);

【注意】:

  1. 在resources下创建package多级文件夹,每一级用分隔符(/)隔开
  2. 如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载,代码如下:
    <mappers>
        <!--Mapper代理开发 加载sql映射文件-->
        <package name="com/itheima/mapper"/>
    </mappers>

【MyBatis核心配置文件】

【核心配置文件的顶层结构】

【注意】:

  • 类型别名(typeAliases)
<typeAliases>
<package name="com.itheima.pojo"/>
</typeAliases>
  • 配置各个标签时,需要遵守前后顺序

【MyBatis实现数据库增删改查】

【利用配置文件完成】

【步骤】

一、准备环境

  1. 数据库表 tb_brand
  2. 实体类 Brand
  3. 测试用例
  4. 安装 MyBatisX 插件

【MyBatisX插件】:是一款基于 IDEA 的快速开发插件,为效率而生。

【功能】

  • XML 和 接口方法 相互跳转
  • 根据接口方法生成 statement

二、功能实现

1.查询所有数据

(1)编写接口方法: Mapper接口

  • 参数:无
  • 结果:List<Brand>
//Mapper接口
List<Brand> selectAll();

(2)编写 SQL语句: SQL映射文件:

<!--SQL映射文件-->
    <!--
        查询所有数据
    -->
    <select id="selectAll" resultType="brand">
        select * from tb_brand;
    </select>

(3)执行方法,测试

 【注意】:实体类属性名 和 数据库表列名 不一致,不能自动封装数据

resultMap:定义<resultMap> 完成不一致的属性名和列名的映射

方法:1.定义<resultMap>标签

           2.在<select>标签中,使用resultMap属性替换resultType

例:

<!--Mapper.xml-->
<!--
    namespace:名称空间
-->
<mapper namespace="com.itheima.mapper.BrandMapper">
    <!--
    id:唯一标识
    type:映射的类型,支持别名
    -->
    <resultMap id="brandResultMap" type="brand">
        <!--
        id:完成主键字段的映射
            column:表的列明
            property:实体类的属性名
        result:完成一般字段的映射
        -->
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>

    <select id="selectAll" resultMap="brandResultMap">
        select id, brand_name, company_name, ordered, description, status
        from tb_brand;

    </select>
//Mapper接口
   //查询所有数据
   List<Brand> selectAll();

//测试类
    public void testSelectAll() throws IOException {
        //加载核心配置文件,获取 SqlSessionFactory 对象
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession对象,执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //执行sql
        List<Brand> brands = brandMapper.selectAll();
        System.out.println(brands);
        //释放资源
        sqlSession.close();
    }

2.查看详情

(1)编写接口方法: Mapper接口

  • 参数:id
  • 结果:Brand
//Mapper接口
Brand selectById(int id);

(2)编写 SQL语句: SQL映射文件

<!--SQL映射文件>    
    <!--
        查看详情
    -->
    <select id="selectById" parameterType="int" resultType="brand">
        select * from tb_brand where id = #{id};
    </select>

(3)执行方法,测试

例:

<!--Mapper.xml-->
<!--
    namespace:名称空间
-->
<mapper namespace="com.itheima.mapper.BrandMapper">
    <!--
    id:唯一标识
    type:映射的类型,支持别名
    -->
    <resultMap id="brandResultMap" type="brand">
        <!--
        id:完成主键字段的映射
            column:表的列明
            property:实体类的属性名
        result:完成一般字段的映射
        -->
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>

    <select id="selectById" resultMap="brandResultMap">
        select id, brand_name, company_name, ordered, description, status
        from tb_brand
        where id = #{id};
        <!--
        #{}:会将其替换为?,为防止SQL注入
        ${}:拼sql,会存在SQL注入
        -->
    </select>
//Mapper接口
   //查看详情
   Brand selectById(int id);

//测试类
public void testSelectById() throws IOException {
        //接受id
        int id = 1;
        //加载核心配置文件,获取 SqlSessionFactory 对象
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession对象,执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //执行sql
        Brand brand = brandMapper.selectById(id);
        System.out.println(brand);
        //释放资源
        sqlSession.close();
    }

【注意】

1.参数占位符:

        1)#{}:执行SQL时,会将#{}占位符替换为?,将来自动设置参数值

        2)${}:拼SQL。会存在SQL注入问题

        3)使用时机: 

                                参数传递,都使用#{}

                                如果要对表名、列名进行动态设置,只能使用${}进行sql拼接。

2. parameterType:

        1)用于设置参数类型,该参数可以省略  

3. SQL 语句中特殊字符处理:

        1)转义字符

        2)<![CDATA[ 内容 ]]>:CD提示

3.条件查询

1.多条件查询——动态条件

(1)编写接口方法: Mapper接口

  • 参数:所有查询条件
  • 结果:List<Brand>
//Mapper接口(三种方式)
//1.散装参数:如果方法中有多个参数,需要使用@Param("SQL参数占位符名称")
List<Brand> selectByCondition(@Param("status")int status, @Param("companyName") String companyName, @Param("brandName") String brandName);

//2.对象参数:对象的属性名称要和参数占位符名称一致
List<Brand> selectByCondition(Brand brand);

//3.map集合参数
List<Brand> selectByCondition(Map map);

(2)编写 SQL语句: SQL映射文件

SQL语句会随着用户的输入或者外部条件的变化而变化,称为动态SQL

<!--SQL映射文件-->
    <!--
        多条件查询-动态
    -->
    <select id="selectByCondition" resultMap="brandResultMap">
        select id, brand_name, company_name, ordered, description, status
        from tb_brand
        <!--where 1=1-->
        <where>
            <if test="status != null">
                and status = #{status}
            </if>
            <if test="companyName != null and companyName !='' ">
                and company_name like #{companyName}
            </if>
            <if test="brandName != null and brandName !='' ">
                and brand_name like #{brandName}
            </if>
        </where>
    </select>

(3)执行方法,测试

例:

<!--Mapper.xml>
<!--
    namespace:名称空间
-->
<mapper namespace="com.itheima.mapper.BrandMapper">
    <!--
    id:唯一标识
    type:映射的类型,支持别名
    -->
    <resultMap id="brandResultMap" type="brand">
        <!--
        id:完成主键字段的映射
            column:表的列明
            property:实体类的属性名
        result:完成一般字段的映射
        -->
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>
    <!--
        多条件查询-动态
    -->
    <select id="selectByCondition" resultMap="brandResultMap">
        select id, brand_name, company_name, ordered, description, status
        from tb_brand
        <!--where 1=1-->
         <where>
            <if test="status != null">
                and status = #{status}
            </if>
            <if test="companyName != null and companyName !='' ">
                and company_name like #{companyName}
            </if>
            <if test="brandName != null and brandName !='' ">
                and brand_name like #{brandName}
            </if>
        </where>
    </select>
//Mapper接口
   //多条件查询(三种方式,后两种需要封装对象)
   List<Brand> selectByCondition(@Param("status")int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
   List<Brand> selectByCondition(Brand brand);
   List<Brand> selectByCondition(Map map);

//测试类
 public void testSelectByCondition() throws IOException {
        //接受参数
        int status = 1;
        String companyName = "华为";
        String brandName = "华为";
        //处理参数
        companyName="%"+companyName+"%";
        brandName="%"+brandName+"%";
        //封装对象
        //Brand对象
/*      Brand brand=new Brand();
        brand.setStatus(status);
        brand.setBrandName(brandName);
        brand.setCompanyName(companyName);*/
        //Map对象
/*      Map map=new HashMap();
        map.put("status",status);
        map.put("companyName",companyName);
        map.put("brandName",brandName);*/
        //加载核心配置文件,获取 SqlSessionFactory 对象
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession对象,执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //执行sql
        List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
        //List<Brand> brands = brandMapper.selectByCondition(brand);
        //List<Brand> brands = brandMapper.selectByCondition(map);
        System.out.println(brands);
        //释放资源
        sqlSession.close();
    }

【注意】

if:用于判断参数是否有值,使用test属性进行条件判断

存在的问题:第一个条件不需要逻辑运算符

解决方案:

1) 使用恒等式让所有条件格式都一样

2) <where> 标签替换 where 关键字

2、单条件查询——动态查询

从多个条件中选择一个

(1)编写接口方法: Mapper接口

  • 参数:所有查询条件
  • 结果:Brand
   //单条件查询
   List<Brand> selectByConditionSingle(Brand brand);

(2)编写 SQL语句: SQL映射文件

<!--SQL映射文件-->
    <!--
        单条件查询-动态
    -->
    <select id="selectByConditionSingle" resultMap="brandResultMap">
        select id, brand_name, company_name, ordered, description, status from tb_brand
        <where>
            <choose><!--相当于switch-->
                <when test="status != null"><!--相当于case-->
                    status = #{status}
                </when>
                <when test="companyName != null and companyName !='' ">
                    company_name like #{companyName}
                </when>
                <when test="brandName != null and brandName !='' ">
                    brand_name like #{brandName}
                </when>
            </choose>
        </where>
    </select>

(3)执行方法,测试

例:

<!--Mapper.xml-->
<!--
    namespace:名称空间
-->
<mapper namespace="com.itheima.mapper.BrandMapper">
    <!--
    id:唯一标识
    type:映射的类型,支持别名
    -->
    <resultMap id="brandResultMap" type="brand">
        <!--
        id:完成主键字段的映射
            column:表的列明
            property:实体类的属性名
        result:完成一般字段的映射
        -->
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>
    <!--
        单条件查询-动态
    -->
    <select id="selectByConditionSingle" resultMap="brandResultMap">
        select id, brand_name, company_name, ordered, description, status from tb_brand
        <where>
            <choose><!--相当于switch-->
                <when test="status != null"><!--相当于case-->
                    status = #{status}
                </when>
                <when test="companyName != null and companyName !='' ">
                    company_name like #{companyName}
                </when>
                <when test="brandName != null and brandName !='' ">
                    brand_name like #{brandName}
                </when>
            </choose>
        </where>
    </select>
   //Mapper接口
   //单条件查询
   List<Brand> selectByConditionSingle(Brand brand);

   //测试类
   public void testSelectByConditionSingle() throws IOException {
        //接受参数
        Integer status = 1;
        String companyName = "华为";
        String brandName = "华为";
        //处理参数
        companyName="%"+companyName+"%";
        brandName="%"+brandName+"%";
        //封装对象
        Brand brand=new Brand();
        brand.setStatus(status);
        brand.setBrandName(brandName);
        brand.setCompanyName(companyName);
        //加载核心配置文件,获取 SqlSessionFactory 对象
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession对象,执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //执行sql
        List<Brand> brands = brandMapper.selectByConditionSingle(brand);
        System.out.println(brands);
        //释放资源
        sqlSession.close();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lx_Hy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值