MyBatis

MyBatis

MyBatis是一款优秀的持久层的框架,用于简化JDBC的开发(JDBC是在java语言使用SQL语言,来调用,修改,添加数据库数据的)

持久层:负责将数据保存到数据库的那一层代码

javaEE三层框架:表现层,业务层,持久层

框架:就是一个半成品的软件,是一套可重用,通用的,软件基础代码模型

在框架的基础上构建软件编写更加高效,规范,可扩张

MyBatis快速入门

查询user表中所有数据

  1. 创建user表,添加数据
  2. 创建模块,导入坐标
  3. 编写MyBatis核心配置文件 --->替换连接信息,解决硬编码问题
  4. 编写SQL映射文件 --->统一管理sql语句,解决硬编码问题
  5. 编码
    1. 定义POJO类
    2. 加载核心配置文件,获取SqlSessionFactory对象
    3. 获取SqlSession对象,执行SQL语句
    4. 释放资源

ait+鼠标左键可以整列编辑

pom.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>com.example</groupId>
    <artifactId>mybatis-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>22</maven.compiler.source>
        <maven.compiler.target>22</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

   <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>8.0.33</version>
       </dependency>
       <!--junit单元测试 -->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.13</version>
           <scope>test</scope>
       </dependency>
       <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>
    <repositories>
        <repository>
            <id>mysql-repo</id>
            <url>https://repo.mysql.com/</url>
        </repository>
    </repositories>
</project>

在pom.xml中加入

<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>8.0.33</version>
       </dependency>
       <!--junit单元测试 -->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.13</version>
           <scope>test</scope>
       </dependency>
       <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>
    <repositories>
        <repository>
            <id>mysql-repo</id>
            <url>https://repo.mysql.com/</url>
        </repository>
    </repositories>

在main的resources中加入logback.xml,mybatis-config.xml和UserMapper.xml

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--    console表示当前日志信息是可以输出到控制台的-->
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>【%level】  %cyan(【%thread】) %boldGreen(%logger{15}) - %msg %n</pattern>
        </encoder>
    </appender>
    <logger name="com.Carter_x" level="DEBUG" additivity="false">
        <appender-ref ref="Console"/>
    </logger>
</configuration>

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>
      <typeAliases>
        <package name="com.pugo"/>
    </typeAliases>
    //起别名之后涉及到USer的实体类是可以直接写user并且不用区分大小写
     <!--
    environments:配置数据库连接环境信息的,可以配置多个environment,通过default属性切换
    -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/blog"/>
                //数据库,端口,
                <property name="username" value="root"/>
                //账户名
                <property name="password" value="ROOT"/>
                //密码
            </dataSource>
        </environment>
         <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/blog"/>
                <property name="username" value="root"/>
                <property name="password" value="ROOT"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--包扫描的方式加载映射文件 -->
        <package name="com.mapper"/>
    </mappers>
</configuration>

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">
<!--
    namepace:名称空间
-->

<mapper namespace="com.mapper.UserMapper">
    <select id="selectAll" resultType="com.ruming.USer">
        select * from login;
    </select>
</mapper>

Mapper代理开发

  1. 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
  2. 设置SQL映射文件的namespace属性为Mapper接口全限定名
  3. 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id并保持参数类型和返回值类型一致
  4. 编码:
    1. 通过SqlSession的getMapper方法获取Mapper接口的代理对象
    2. 调用对应方法完成sql的执行

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

 //1. 加载mysql的核心配置文件,获取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("test.selectAll");
        //获取BrandMapper代理对象
        BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
        List<Brand> brands = brandmapper.selectAll();
        System.out.println(brands);
        sqlSession.close();

MyBatis核心配置文件

顶层结构

configuration(配置)

  • Properties(属性)

  • settings(设置)

  • typeAliases(类型别名)

  • typeHandlers(类型处理器)

  • objectFactory(对象工厂)

  • plugins(插件)

  • environments(环境配置)

    environment(环境变量)

    • transactionManager(事务管理器)
    • dataSource(数据源)
  • darabaseldProvider(数据库厂商标识)

  • mapper(映射器)

配置便签时,要注意遵守前后顺序

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>
      <typeAliases>
        <package name="com.pugo"/>
    </typeAliases>
    //起别名之后涉及到USer的实体类是可以直接写user并且不用区分大小写
     <!--
    environments:配置数据库连接环境信息的,可以配置多个environment,通过default属性切换
    -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis_demo"/>
                //数据库,端口,
                <property name="username" value="root"/>
                //账户名
                <property name="password" value="ROOT"/>
                //密码
            </dataSource>
        </environment>
         <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/blog"/>
                <property name="username" value="root"/>
                <property name="password" value="ROOT"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--包扫描的方式加载映射文件 -->
        <package name="com.mapper"/>
    </mappers>
</configuration>

配置文件完成增删改查

用一个案例来演示

要完成的功能列表清单

  1. 查询

    查询所有数据

    查看情况

    条件查询

  2. 添加

  3. 修改

    修改全部字段

    修改动态字段

  4. 删除

    删除一个

    批量删除

查看所有数据

数据库名和实体类名不一样

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

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

    select id,brand_name as brandName,company_name as companyName,order from tb_brand;

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

    可以使用sql片段

    <sql id="sqlbrand">

  • resultMap:定义<resultMap>标签,在<select>标签中,使用resultMap属性替换resultType属性

    id:唯一标识

    type:映射的类型,支持别名

    <resultMap id="brandResultMap" type="brand">
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
        <resultMap>
        <select id="selectAll" rseultMap="brandResultMap">
    

    resultMap的标签内部:

    id:完成主键字段的映射

    • column:表的列名
    • property:实体类的属性名

    result:完成一般字段的映射

    • column:表的列名
    • property:实体类的属性名

编写接口方法:Mapper接口

  • 参数:无
  • 结果:List<Brand>

编写SQL语句:SQL映射文件

执行方法,测试

BrandMapper.java,BrandMapper接口

package com.mapper;
import com.pugo.Brand;
import java.util.List;
public interface BrandMapper {
    List<Brand> selectAll();
}

BrandMapper.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">
<!--
    namepace:名称空间
-->
<mapper namespace="com.mapper.BrandMapper">
    <select id="selectAll" resultType="Brand">
    select *
    from tb_brand;
    </select>
</mapper>

MybatisTest.java,测试代码

public class MybatisTest {
    @Test
    public void test() throws IOException {
        //1. 加载mysql的核心配置文件,获取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("test.selectAll");
        //获取BrandMapper代理对象
        BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
        List<Brand> brands = brandmapper.selectAll();
        System.out.println(brands);
        sqlSession.close();
    }
}

查看详情

  1. 编写接口方法:Mapper接口

    参数:id

    结果:Brand

  2. 编写SQL语句:SQl映射文件

    <select id="selectByld" parameterType="int" resultType="brand">
        select * from tb_brand where id=#{id};</select>
    
  3. 执行方法,测试

参数占位符:

  1. {}:会将其替换为?,为了防止SQL注入

  2. ${}:拼sql。会有SQL注入问题
  3. 使用时机:
    • 参数传递的时候:#{}
    • 表名或者列名不固定的情况下:${}会存在SQL注入问题

参数类型:parameterType:可以省略

特殊字符处理:

  1. 转义字符:<(小于号)的转义字符 &it
  2. CDATA区:<![CDATA[ < ]]>
    List<Brand> selectByid(int id);

<--      -->
    
       <select id="selectByid" resultType="com.pugo.Brand">
        select *
        from tb_brand where id=#{id};
    </select>
        
        
        List<Brand> brands = brandmapper.selectByid(id);

查询-多条件查询

  1. 编写接口方法:Mapper接口

    参数:所有查询条件

    结果:List<Brand>

  2. 编写SQL语句:SQL映射文件

  3. 执行方法,测试

参数接收:

  1. 散装参数:如果方法中有多个参数,需要使用@Param("SQL参数占位符名称")

    List<Brand> selectByCondition(@Param("status") int status,@Param("companyName") String companyName)
    
  2. 对象参数:对象的属性名要和参数的名称对应

    List<Brand> selectByCondition(Brand brand);
    //Brand类的属性名要和需要的参数名对应,属性的值就是参数的值
    
    
     <select id="selectByCondition" resultType="com.pugo.Brand">
            select *
            from tb_brand where id=#{id} and company_name like #{company_name} and brand_name like #{brand_name};
        </select>
    
        int start = 1;
            String companyName="三只松鼠";
            String brandName="";
            companyName = "%"+companyName+"%";
            brandName = "%"+brandName+"%";
            Brand brand = new Brand();
            brand.setId(start);
            brand.setBrand_name(brandName);
            brand.setCompany_name(companyName);
    
    
    List<Brand> brands = brandmapper.selectByCondition(brand);
    
  3. map集合参数:其中的键要和参数名对应

    List<Brand> selectByCondition(Map map);
    //Map中的键名要和参数名称对应,键值就是参数值
    
    Map map= new HashMap();
    map.put("id",id);
    map.put("companyName",compantName);
    map.put("brandName",brandName);
    

查询-多条件-动态条件查询动态SQL

动态SQL

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

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

解决方法:

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

    在where后面加上1=1,所有的都加上and

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

    <where>
    <if test="compantName !=null and companyName !=''">
    and company_name like #{companyName}</if>
    <if test="brandName!=null">
    and brandName like #{brandName}</if>
    </where>
    

从多个条件中选一个

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

select * from tb_brand
<where>
<choose><!-- 类似与switch-->
<when test="status!=null"><!-- 类似于case-->
status=#{status}
</when>
<otherwise><!--类似于default-->
1=1
</otherwise>
</choose>
</where>

添加

编写接口方法:Mapper接口 void add(Brand brand);

  • 参数:除了id之外的所有数据
  • 结果:void

编写SQL语句:SQL映射文件

<insert id="add">
insert into tb_brand(brand_name,company_name,ordered,description,status) values(#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>

执行方法,测试

  • MyBatis事务

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

     String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //2. 获取sqlSession对象,用它库执行sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //执行sql
           //获取BrandMapper代理对象
            BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
    //执行方法
    brandmapper.add(brand);
    //提交事务
    sqlSession.commit();
    //释放资源
    sqlSession.close();
    

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

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

添加的主键返回,让主键能在添加的类的没有设但主键自增的值能实时返回,在添加后就能通过实体类使用。<insert useGeneratedKeys="true" keyProperty="id">

<insert useGeneratedKeys="true" keyProperty="id">

   //执行方法
brandmapper.add(brand);
//提交事务
sqlSession.commit();
Integer id=brand.getid();
System.out.println(id);
//id能打印出来就是主键自增的那个值
//释放资源
sqlSession.close();
        

修改

编写接口方法:Mapper接口 void update(Brand brand)

  • 参数:所有数据
  • 结果:void

编写SQL语句:SQL映射文件

<update id="update">
update tb_brand set brand_name=#{brandName},company_name=#{companyName},orderd=#{orderd},description=#{description},status=#{status}
where id = #{id}
</update>

执行方法。测试

动态修改

<set>,<if>标签

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

删除

sqlw文件:

<delete id="deleteByid">
delete from tb_brand where id=#{id};
</delete>

批量删除

接收一个id数组,循环遍历删除

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

  • 默认:array=数组
  • 使用@Param注解改变map集合的默认名称(@Param(ids))在BrandMApper方法中的参数ids前放上注解

<foreach>:循环遍历便签

collection:循环的对象,item:循环时的名称

separator:用什么分隔符,比如 ,,open:开始添加什么,close:结束时添加什么

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

参数传递

MyBatis参数封装:

  1. POJO类型(实体类):直接使用,属性名和参数占位符名称一致

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

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

    map.put("arg0",collection集合);

    map.put("collection",collection集合)

  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",Array集合);

    map.put("array",Array集合)

  6. 其他类型:直接使用

多个参数:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

map.put("arg0",参数1);

map.put("param1",参数2);

map.put("param2",参数3);

map.put("arg1",参数4);

----------------@Param("username")

map.put("username",参数1);

map.put("param1",参数2);

map.put("param2",参数3);

map.put("arg1",参数4);

使用@Param注解

注解完成增删改查

注解完成简单功能

配置文件完成复杂功能

@Select("select * from tb_brand where id=#{id}")
public Brand selectByid(int id);

在mapper上的方法上面写这个注解

  • 查询:@Select
  • 添加:@Insert
  • 修改:@Update
  • 删除:@Delete
posted @ 2025-04-08 19:54  畏惧不前  阅读(30)  评论(0)    收藏  举报