Mybatis学习笔记

MyBatis

什么是MyBatis?

  • MyBatis是一款优秀的持久层框架,用于简化JDBC开发
  • MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github
  • 官网:https://mybatis.org/mybatis-3/zh/index.html

持久层

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

框架

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

JDBC 缺点

1.硬编码

  • 注册驱动,获取连接
  • SQL语句

2.操作繁琐

  • 手动设置参数
  • 手动封装结果集

MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作

MyBatis快速入门

  1. 创建表mybatisdemo数据库,创建user表,添加数据

  2. 创建模块,导入坐标

    //pro.xml
    <?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.jihua</groupId>
        <artifactId>mavendemo</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
        </properties>
    
        <dependencies>
            <!--导入MySQL驱动jar包-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.34</version>
            </dependency>
            <!--导入druid-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.12</version>
            </dependency>
            <!--导入junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13</version>
                <scope>test</scope>
            </dependency>
    
            <!--mybatis依赖-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.5</version>
            </dependency>
    
            <!--添加slf4j日志api-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.20</version>
            </dependency>
            <!--添加logback-classic依赖-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.3</version>
            </dependency>
            <!--添加logback-core依赖-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
        </dependencies>
    </project>
    
  3. 编写MyBatis核心配置文件---->替换连接信息解决硬编码问题

    //mybatis-config.xml
    <?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:///mybatisdemo?useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="修改为你的密码"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <!--加载sql映射文件-->
            <mapper resource="UserMapper.xml"/>
        </mappers>
    </configuration>
    
  4. 编写SQL映射文件---->统一管理sql语句,解决硬编码问题

    //UserMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--
        namespace:名称空间
    -->
    <mapper namespace="demo">
        <select id="selectAll" resultType="com.jihua.pojo.User">
            select *
            from tb_user
        </select>
    </mapper>
    
  5. 编码

    (1) 定义POJO类

    //User类
    package com.jihua.pojo;
    
    public class User {
        private Integer id;
        private String username;
        private String password;
        private String gender;
        private String addr;
    
        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 getAddr() {
            return addr;
        }
    
        public void setAddr(String addr) {
            this.addr = addr;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", gender='" + gender + '\'' +
                    ", addr='" + addr + '\'' +
                    '}';
        }
    }
    

    (2) main方法内

    //mybatisDemo类
    package com.demo;
    
    import com.jihua.pojo.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 java.io.InputStream;
    import java.util.List;
    
    public class mybatisDemo {
        public static void main(String[] args) throws Exception {
            //1.加载mybatis的核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //2.获取SqlSession对象,用它来执行sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            //3. 执行sql
            List<User> users = sqlSession.selectList("demo.selectAll");
    
            System.out.println(users);
    
            //4. 释放资源
            sqlSession.close();
        }
    }
    

Mapper代理开发

目的

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

使用Mapper 代理方式完成入门案例

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

    1. 新建UserMapper接口,放在src/main/java/com/jihua/Mapper下

    2. 将UserMapper.xml文件放在src/main/resources/com/jihua/Mapper下

    • 注意:在resources目录下创建多级目录不能用.,要用/,例如创建包时可以使用com.jihua.Mapper,但是resources目录只能使用com/jihua/Mapper
  2. 设置SQL映射文件的namespace属性为Mapper接口全限定名

    //UserMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--
        namespace:名称空间
    -->
    <mapper namespace="com.jihua.Mapper.UserMapper">
        <select id="selectAll" resultType="com.jihua.pojo.User">
            select *
            from tb_user
        </select>
    </mapper>
    
  3. 在 Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致

    //UserMapper接口
    package com.jihua.Mapper;
    
    import com.jihua.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
        List<User> selectAll();
    }
    
  4. main方法中

    //mybatisDemo类
    package com.demo;
    
    import com.jihua.Mapper.UserMapper;
    import com.jihua.pojo.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 java.io.InputStream;
    import java.util.List;
    
    public class mybatisDemo {
        public static void main(String[] args) throws Exception {
            //1.加载mybatis的核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //2.获取SqlSession对象,用它来执行sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            //3. 执行sql
            //3.1 通过SqlSession的getMapper方法获取Mapper接口的代理对象
            UserMapper UserMapper = sqlSession.getMapper(UserMapper.class);
            //3.2 调用对应方法完成sql的执行
            List<User> users = UserMapper.selectAll();
    
            System.out.println(users);
    
            //4. 释放资源
            sqlSession.close();
        }
    }
    

细节:如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载

//mybatis-config.xml文件下的mappers修改为
<mappers>
    <!--加载sql映射文件-->
    <!--<mapper resource="com/jihua/Mapper/UserMapper.xml"/>使用Mapper代理后弃用-->
    <!--Mapper代理方式-->
    <package name="com.jihua.Mapper"/>
</mappers>

MyBatis核心配置文件

MyBatis核心配置文件的顶层结构如下:.

  • configuration(配置)
    • properties(属性)
    • settings(设置)
    • typeAliases(类型别名)
    • typeHandlers(类型处理器)
    • objectFactory (对象工厂)
    • plugins(插件)
    • environments(环境配置)
      • environment(环境变量)
        • transactionManager(事务管理器)
        • dataSource(数据源)
    • databaseldProvider (数据库厂商标识)
    • mappers(映射器)

类型别名(typeAliases)

<typeAliases >
	<package name="com.jihua.pojo"/>
</typeAliases>

细节:配置各个标签时,需要遵守前后顺序

配置文件完成增删改查

  • 要完成的功能列表清单:
    1. 查询
      • 查询所有数据
      • 查看详情
      • 条件查询
    2. 添加
    3. 修改
      • 修改全部字段
      • 修改动态字段
    4. 删除
      • 删除一个
      • 批量删除

查询

数据库表的字段名称实体类的属性名称不一样,则不能自动封装数据

  • 起别名:对不一样的列名起别名,让别名和实体类的属性名一样

    • 缺点:每次查询都要定义一次别名

      select 
      	id, use_name as useName 
      from 
      	tb_use;
      
  • sql片段

    • 缺点:不灵活

      <sql id="usenamechange">
      	id, use_name as neme
      </sql>
      
      <select id="selectAll" resultType="user">
          select
          	<include refid="usenamechange" />
          from tb_user;
      </select>
      
  • resultMap

    1.定义标签
    2.在标签中,使用resultMap属性替换resultType属性

    resultMap属性:

    • id:唯一标识
    • type:映射的类型,支持别名

    resultMap内部:

    • id:完成主键字段的映射

      • column:表的列名
      • property:实体类的属性名
    • result:完成一般字段的映射

      • column:表的列名
      • property:实体类的属性名
    <resultMap id="nameReaultMap" type="user">
        <redult column="user_name" property="userName" />
    </resultMap>
    
    <select id="selectAll" resultMap="nameResultMap">
        select
        	*
        from 
        	tb_user;
    </select>
    
动态查询(接收传入的id值查询)

参数占位符:

  1. #{ }:会将其替换为?,为了防止SQL注入
  2. ${ }:拼sql。会存在SQL注入问题
  3. 使用时机:
    • 参数传递的时候:#{ }
    • 表名或者列名不固定的情况下:${}。会存在SQL注入问题

参数类型: parameterType:可以省略

<select id="selectById" parameterType="int" resultNap="brandResultMap">
	select 
    	*
	from 
    	tb_brand 
    where 
    	id = #{id};
</select>

使用方法:

//4.执行方法
User user = userMapper.selectById(id);
system.out.println(user);

同时接口里应该有方法:

User selectById(int id);

特殊字符处理:

  1. 转义字符:例如&lt;表示<

  2. CDATA区:IDEA中敲CD直接回车

    <![CDATA[
    	在这里可以写小于号
    ]]>
    
条件查询

sql语句:

<select id="selectBycondition" resultMap="brandResultMap">
	select *
	from tb_brand
	where status = #{status}
		and company_name like #{companyName}
    	and brand_name like #{brandName}
</select>

参数接收

  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集合参数:

    接收前端传入的数据后,封装为一个map集合,其中键的名称要和参数占位符名称一致

    List<Brand> selectByCondition(Map map) ;
    
多条件动态查询

当用户查询时并没有用到所有条件限制时,要采用动态SQL

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

<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where
    	<if test="status != null">
            status = #{status}
    	</if>
    	<if test="companyName != null and companyName != '' ">
            and company_name = #{companyName}
    	</if>
    	<if test="brandName != null and brandName != '' ">
            and brand_name = #{brandName}
    	</if>
</select>

MyBatis 对动态SQL有很强大的支撑:

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

上面的代码如果第一个参数也没有传入,会导致拼接的sql语法错误

解决方法:

  1. 恒等式

    添加一个1=1条件

    <select id="selectByCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        where 1 = 1
        	<if test="status != null">
                and status = #{status}
        	</if>
        	<if test="companyName != null and companyName != '' ">
                and company_name = #{companyName}
        	</if>
        	<if test="brandName != null and brandName != '' ">
                and brand_name = #{brandName}
        	</if>
    </select>
    
  2. 替换where关键字

    mybatis自带的条件处理

    <select id="selectByCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        <where>
        	<if test="status != null">
                and status = #{status}
        	</if>
        	<if test="companyName != null and companyName != '' ">
                and company_name = #{companyName}
        	</if>
        	<if test="brandName != null and brandName != '' ">
                and brand_name = #{brandName}
        	</if>
           </where>
    </select>
    
多条件动态查询
  • 从多个条件中选择一个

  • choose (when, otherwise):选择,类似于Java中的switch语句

    <select id="111" resultType="com.jihua.pojo.User">
        select *
        from tb_user
        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>
            <otherwise><!--类似于default-->
                1=1
            </otherwise>
        </choose>
    </select>
    

添加

MyBatis事务:

在获取sqlSession对象时

//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();

openSession():默认开启事务,进行增删改操作后需要使用sqlSession.commit();手动提交事务

openSession(true):可以设置为自动提交事务(关闭事务)

在数据添加成功后,需要获取插入数据库数据的主键的值

只需要添加两个属性:

​ useGeneratedKeys:开启主键返回

​ keyProperty:指向对应主键名称

<insert id="addOrder" useGeneratedKeys="true" keyProperty="id">
    insert into tb_order (payment,paymlent_type,status) values (#{payment},#{paymentType},#{status});
</insert>

修改

:

​ 使用set标签处理参数个数导致的sql语法问题

<update id="update">
    update tb_brand
    <set>
        <if test="brandName != null and brandName !=''">
            brand_name = #{brandName},
        </if>
		<if test="companyName != null and companyName !=''">
            company_name = #{companyName},
		</if>
		<if test="ordered != null">
            ordered = #{ordered},
        </if>
		<if test="description != null and description !=''">
            description = #{description},
		</if>
		<if test="status != null">
            status = #{status},
        </if>
	</set>
	where id = #{id};
</update>

删除

<delete id="deleteById">
	delete from tb_brand where id =#{id};
</ delete>
  • 批量删除

    传入一个id的数组

    <delete id="deleteBylds">
    	delete from tb_brandwhere id in (?,?,?)
    </delete>
    

    mybatis会将数组参数,封装为一个Map集合

    • 默认::array =数组

    • 或者:使用@Param注解改变map集合的默认key的名称

      //定义接口方法时
      void deleteByIds (@Param("ids") int[] ids);
      

    in(?, ?, ?)中具体有多少个?,需要遍历数组,需要使用标签

    <delete id="deleteBylds">
        delete from tb_brand
        where id in
    	<foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
    	</foreach>
    </delete>
    

    separator属性表示自动添加分隔符,openclose属性会加在开始和结束的位置

MyBatis参数传递

MyBatis 接口方法中可以接收各种各样的参数,MyBatis底层对于这些参数进行不同的封装处理方式

MyBatis参数封装:

MyBatis提供了ParamNameResolver类来进行参数封装

  • 单个参数
  1. POJO(数据结构)类型:直接使用,属性名和参数占位符名称一致

  2. Map集合:直接使用,键名和参数占位符名称一致

  3. Collection:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

    map .put( "arg0" ,list集合);
    map.put( "collection " ,list集合);
    
  4. List:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

    map .put( "arg0" ,list集合);
    map .put( "collection " ,list集合);
    map.put( "list",list集合);
    
  5. Array:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

map. put ( " arg0",数组);
map. put( " array ",数组);
  1. 其他类型:直接使用
  • 多个参数:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

    map.put ("arg0",参数值1);
    map.put("param1",参数值1);
    map.put("agr1",参数值2);
    map.put("param2",参数值2);
    /设置@Param ( "username " )
    map.put("username",参数值1);
    map.put("param1",参数值1);
    map.put("agr1",参数值2);
    map.put("param2",参数值2);
    

建议:将来都使用@Param注解来修改Map集合中默认的键名,并使用修改后的名称来获取值,这样可读性更高!

注解完成增删改查

使用注解开发会比配置文件开发更加方便

@Select("select * from tb_user where id = #{id}")
public User selectByld(int id);
  • 查询:@Select
  • 添加: @Insert
  • 修改:@Update
  • 删除:@Delete

提示:

  • 注解完成简单功能

  • 配置文件完成复杂功能

  • 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java注解不仅力不从心,还会让你本就复杂的SOL语句更加是盟不堪。因此,如果你需要做一些很复杂的操作,最好用XML来映射语句。

  • 选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。换句话说,永远不要拘况于一种方式。你可以很轻松的在基于注解和XML的涯句缺射舫j方式睚自由移植和切换。

动态SQL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值