MyBatis

MyBatis

  1. 概述

  2. Mybatis 要优于之前的 JDBC

  3. MyBatis快速入门

    • 如果SQL语句返回的是集合,比如List<User> ,resultType属性的值只需要写泛型类型就行,也就是 User

    • 项目结构 - 接口与 xml文件层级对应

  4. 日志

    • log4j的pom坐标

      <!-- log start -->
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.12</version>
      </dependency>
      
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.6.6</version>
      </dependency>
      
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.6.6</version>
      </dependency>
      
    • log4j.properties

      ##设置日志记录到控制台的方式
      log4j.appender.std=org.apache.log4j.ConsoleAppender
      log4j.appender.std.Target=System.err
      log4j.appender.std.layout=org.apache.log4j.PatternLayout
      log4j.appender.std.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n
      
      ##设置日志记录到文件的方式
      log4j.appender.file=org.apache.log4j.FileAppender
      log4j.appender.file.File=mylog.txt
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
      
      ##日志输出的级别,以及配置记录方案,级别越低(error>warn>info>debug>trace),打印的信息越多。
      ##开发一般写debug,std(控制台显示)。项目上线推荐使用error,file。
      log4j.rootLogger= info,std,file    
      

在这里插入图片描述

  1. Mapper接口使用规范

  2. 核心配置文件SqlMapConfig.xml详解

    • 文件结构

    • properties(引入配置文件)

    • typeAliases(类型别名)

      • typeAliases起别名,如果用package,会给一个文件夹起别名,但是你用里面的实体类时,返回值参数你就要用全小写
    • environments(环境配置)

    • mappers

      · mappers:配置关联映射文件 - 要么提供xml文件路径( ‘/’ 分隔),要么提供接口的路径( ‘.’ 分隔)
      按照mapper.xml路径配置 使用/分割路径
      按照接口文件路径配置 使用.分割路径
      批量配置 使用.分割路径,只需要配置包名。不需要设置具体的接口名。

MyBatis 练习

  1. 配置文件完成增删改查

    • 查询 - 查询所有商品

      ~ 注意事项

    • 查询 - 查看商品详情

    • 查询 - 模糊查询

      ~ ${value} 和 #{value}的区别

    • 查询 - 多条件查询
      @Param主要是用来注解dao类中方法的参数,便于在对应的dao.xml文件中引用。

    • 添加 - 添加商品信息

      ~ 增删改需要提交事务才会真的生效,或者当初创建开会话的时候设置自动提交

    • 添加 - 添加订单信息 (主键自增回填 - 拿到自增后的 id,有的时候要用)

在这里插入图片描述

 ~ order属性的值AFTER :用于等算法生成独特 id 再新增数据的情况。
  • 修改 - 修改商品所有信息

  • 删除 - 删除指定商品

  • 使用注解的测试类 - 测试方法

    public class MyBatisTest {
        //工厂对象
        private static SqlSessionFactory factory;
        //会话对象
        private SqlSession sqlSession;
        //代理对象
        private BrandDao brandDao;
    
        //快捷键:快速转成全局变量  Ctrl+Alt+F
        @BeforeClass
        public static void getSqlFactory() throws Exception {
            //获取核心文件输入流
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //获取工厂创建对象
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //获取工厂对象
            factory = builder.build(in);
        }
    
        @Before
        public void getSqlSession() {
            //获取会话对象
            //是否开启事务,由具体业务需求决定的。
            //openSession() 默认开启事务管理
            sqlSession = factory.openSession();
            //openSession(boolean var1 ) 设置自动提交事务,var1值设置为true之后,增删改操作会自动提交事务
            //sqlSession = factory.openSession(true);
            //获取代理对象
            brandDao = sqlSession.getMapper(BrandDao.class);
        }
    
        @Test
        public void testSelectAll() throws Exception {
            //执行sql操作
            List<Brand> brands = brandDao.selectAll();
            //处理结果
            for (Brand brand : brands) {
                System.out.println(brand);
            }
        }
    
        @Test
        public void testSelectById() throws Exception {
            //执行sql操作
            int id = 1;
            Brand brand = brandDao.selectById(id);
            //处理结果
            System.out.println(brand);
        }
    
        @Test
        public void testSelectByBrandName() throws Exception {
            //执行sql操作
            String brandName = "华为";
            List<Brand> brands = brandDao.selectByBrandName(brandName);
            //处理结果
            for (Brand brand : brands) {
                System.out.println(brand);
            }
        }
    
        @Test
        public void testSelectByConditions1() throws Exception {
            //执行sql操作
            int status = 1;
            String conpanyName = "有限公司";
            String brandName = "华为";
            List<Brand> brands = brandDao.selectByConditions1(status, conpanyName, brandName);
            //处理结果
            for (Brand brand : brands) {
                System.out.println(brand);
            }
        }
    
        @Test
        public void testSelectByConditions2() throws Exception {
            //执行sql操作
            int status = 1;
            String companyName = "有限公司";
            String brandName = "华为";
            //List<Brand> brands = brandDao.selectByConditions2(status, conpanyName, brandName);
            Brand brand = new Brand();
            brand.setStatus(status);
            brand.setCompanyName(companyName);
            brand.setBrandName(brandName);
            //List<Brand> brands = brandDao.selectByConditions2(brand);
            Map brandMap = new HashMap<>();
            brandMap.put("status", status);
            brandMap.put("companyName", companyName);
            brandMap.put("brandName", brandName);
            List<Brand> brands = brandDao.selectByConditions2(brandMap);
            //处理结果
            for (Brand brand2 : brands) {
                System.out.println(brand2);
            }
        }
    
        @Test
        public void testInsertBrand() throws Exception {
            //执行sql操作
            Brand brand = new Brand();
            brand.setBrandName("华为荣耀");
            brand.setCompanyName("华为技术有限公司");
            brand.setOrdered(102);
            brand.setDescription("一家伟大的公司...");
            brand.setStatus(1);
            brandDao.insertBrand(brand);
    
            //因为sqlSession默认开启事务管理,如果执行增删改,必须手动提交事务。
            sqlSession.commit();
        }
    
        @Test
        public void testInsertBrandGetID() throws Exception {
            //执行sql操作
            Brand brand = new Brand();
            brand.setBrandName("华为荣耀");
            brand.setCompanyName("华为技术有限公司");
            brand.setOrdered(102);
            brand.setDescription("一家伟大的公司...");
            brand.setStatus(1);
    
            System.out.println("brand.getId:" + brand.getId());//null
    
            brandDao.insertBrandGetID(brand);
            //因为sqlSession默认开启事务管理,如果执行增删改,必须手动提交事务。
            sqlSession.commit();
    
            //获取回填数据
            System.out.println("brand.getId:" + brand.getId());//xx
        }
    
        @Test
        public void testUpdateBrand() throws Exception {
            //执行sql操作
            Brand brand = new Brand();
            brand.setId(14);
            brand.setBrandName("华为荣耀666");
            brand.setCompanyName("华为666");
            brand.setOrdered(105);
            brand.setDescription("一家特别伟大的公司...");
            brand.setStatus(0);
            brandDao.updateBrand(brand);
    
            //因为sqlSession默认开启事务管理,如果执行增删改,必须手动提交事务。
            sqlSession.commit();
        }
    
        @Test
        public void testDeleteById() throws Exception {
            //执行sql操作
            int id = 14;
            brandDao.deleteById(id);
    
            //因为sqlSession默认开启事务管理,如果执行增删改,必须手动提交事务。
            sqlSession.commit();
        }
    
        @After
        public void closeSqlSession() {
            //关闭会话对象
            sqlSession.close();
        }
    }
    
  • BrandDao.java - 定义了增删改查等操作方法

    public interface BrandDao {
        //查看所有产品
        List<Brand> selectAll();
        //查看商品详情
        Brand selectById(int id);
        //模糊搜索
        List<Brand> selectByBrandName(String brandName);
        //多条件查询
        List<Brand> selectByConditions1(int status, String companyName, String brandName);
        //List<Brand> selectByConditions2(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
        //List<Brand> selectByConditions2(Brand brand);
        List<Brand> selectByConditions2(Map brandMap);
        //添加商品
        void insertBrand(Brand brand);
        //添加订单信息(主键自增回填)
        void insertBrandGetID(Brand brand);
        //修改商品信息
        void updateBrand(Brand brand);
        //删除商品
        void deleteById(int id);
    }
    
  • BrandDao.xml - 增删改查方法具体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">
    <mapper namespace="com.itheima.dao.mapper.BrandDao">
        <resultMap id="brandResultMap" type="brand">
            <result column="brand_name" property="brandName"></result>
            <result column="company_name" property="companyName"></result>
        </resultMap>
        <!--查询所有产品-->
        <!--解决数据库字段名与实体类属性名不一致问题:方式1-->
        <!--<select id="selectAll" resultType="brand">
            select id, brand_name AS brandName, company_name AS companyName, ordered, description, status from tb_brand;
        </select>-->
    
        <!--解决数据库字段名与实体类属性名不一致问题:方式2 引入结果映射-->
        <select id="selectAll" resultMap="brandResultMap">
            SELECT *
            FROM tb_brand;
        </select>
    
        <!--查询商品详情-->
        <!--<select id="selectById" resultMap="brandResultMap" parameterType="int">
            select *
            from tb_brand where id=${id};
        </select>-->
        <select id="selectById" resultMap="brandResultMap" parameterType="int">
            SELECT *
            FROM tb_brand
            WHERE id = #{id};
        </select>
    
        <!--模糊搜索-->
        <!--<select id="selectByBrandName" resultMap="brandResultMap" parameterType="String">
            select *
            from tb_brand WHERE brand_name LIKE '%${brandName}%';
        </select>-->
        <select id="selectByBrandName" resultMap="brandResultMap" parameterType="String">
            SELECT *
            FROM tb_brand
            WHERE brand_name LIKE CONCAT('%', #{brandName}, '%');
        </select>
    
        <!--多条件查询-->
        <select id="selectByConditions1" resultMap="brandResultMap">
            SELECT *
            FROM tb_brand
            WHERE status = #{arg0}
              AND company_name LIKE CONCAT('%', #{arg1}, '%')
              AND brand_name LIKE CONCAT('%', #{arg2}, '%');
        </select>
        <select id="selectByConditions2" resultMap="brandResultMap">
            SELECT *
            FROM tb_brand
            WHERE status = #{status}
              AND company_name LIKE CONCAT('%', #{companyName}, '%')
              AND brand_name LIKE CONCAT('%', #{brandName}, '%');
        </select>
    
        <!--添加商品-->
        <insert id="insertBrand">
            INSERT INTO tb_brand
            VALUES (NULL, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
        </insert>
        <!--添加订单信息(主键自增回填)-->
        <!--useGeneratedKeys表示是否自增回填  true表示要自增回填-->
        <!--keyProperty 对应实体类的中是属性-->
        <!--<insert id="insertBrandGetID" useGeneratedKeys="true" keyProperty="id">-->
        <!--    INSERT INTO tb_brand-->
        <!--    VALUES (NULL, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status});-->
        <!--</insert>-->
        <!--resultType:键返回类型-->
        <!--keyColumn:键对应的是数据库的哪个字段-->
        <!--keyProperty:对应实体类的中是属性-->
        <!--order:表示获取insert执行前(BEFORE)还是执行后(AFTER)的键值-->
        <insert id="insertBrandGetID">
            <selectKey resultType="int" keyColumn="id" keyProperty="id" order="AFTER">
                SELECT LAST_INSERT_ID()
            </selectKey>
            INSERT INTO tb_brand
            VALUES (NULL, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
        </insert>
        <!--修改商品信息-->
        <update id="updateBrand">
            UPDATE tb_brand
            SET brand_name   = #{brandName},
                company_name = #{companyName},
                ordered      = #{ordered},
                description  = #{description},
                status       = #{status}
            WHERE id = #{id};
        </update>
    
        <!--删除商品-->
        <delete id="deleteById">
            DELETE FROM tb_brand WHERE id = #{id};
        </delete>
    </mapper>
    
  1. 动态 SQL - 优化 xml文件中的SQL语句,解决较为复杂的SQL语句

    • 概述

    • 查询 - 动态条件查询

在这里插入图片描述

  • 修改 - 动态修改商品信息

在这里插入图片描述

  • 批量删除

  • 使用注解的测试类

    public class MyBatisTest {
    
        private static SqlSessionFactory factory;
        private SqlSession sqlSession;
        private BrandDao brandDao;
    
        @BeforeClass
        public static void getSQLFactory() throws Exception {
            //获取核心文件输入流
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //获取工厂常见对象
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //获取工厂对象
            factory = builder.build(in);
        }
    
        @Before
        public void getSqlSession() {
            //获取会话对象
            sqlSession = factory.openSession();
            //获取代理对象
            brandDao = sqlSession.getMapper(BrandDao.class);
        }
    
        @Test
        public void testSelectByConditions() {
            //执行操作
            Integer status = null;
            String companyName = "华为";
            String brandName = "华为";
            Brand brand = new Brand();
            brand.setStatus(status);
            brand.setCompanyName(companyName);
            brand.setBrandName(brandName);
            List<Brand> brands = brandDao.selectByConditions(brand);
            //处理数据
            for (Brand brand2 : brands) {
                System.out.println(brand2);
            }
    
        }
    
        @Test
        public void testUpdateBrand() {
            //执行操作
            Brand brand = new Brand();
            brand.setId(11);
            brand.setBrandName("华为");
            brand.setCompanyName("华为");
            brand.setOrdered(105);
            brand.setDescription("最佳公司");
            //brand.setStatus(1);
            brand.setStatus(null);
    
            brandDao.updateBrand(brand);
            sqlSession.commit();
        }
    
        @Test
        public void testDeleteByIds() {
            //执行操作
            int[] ids = {7,8,9};
    
            brandDao.deleteByIds(ids);
            sqlSession.commit();
        }
    
        @After
        public void closeSqlSession() {
            //关闭资源
        }
    }
    
  • BrandDao.java

    public interface BrandDao {
        //多条件动态查询
        List<Brand> selectByConditions(Brand brand);
        //动态修改商品信息
        void updateBrand(Brand brand);
        //批量删除
        void deleteByIds(@Param("ids") int[] ids);
    }
    
  • BrandDao.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">
    <mapper namespace="com.itheima.dao.mapper.BrandDao">
        <resultMap id="brandResultMap" type="brand">
            <result column="brand_name" property="brandName"></result>
            <result column="company_name" property="companyName"></result>
        </resultMap>
        <!--定义sql片段-->
        <sql id="selectBrandSql">
            SELECT *
            FROM tb_brand
        </sql>
    
        <!--动态条件查询-->
        <!--下面的写法,当status为null的时候,会造成sql语句语法错误(where后面跟了一个and)-->
        <!--<select id="selectByConditions" resultMap="brandResultMap">
             SELECT * FROM tb_brand
             WHERE
             <if test="status!=null">
                 status = #{status}
             </if>
             <if test="companyName!=null and companyName!=''">
                 AND company_name LIKE CONCAT('%', #{companyName}, '%');
             </if>
             <if test="brandName!=null and brandName!=''">
                 AND brand_name LIKE CONCAT('%', #{brandName}, '%')
             </if>
         </select>-->
        <!--可以在where后面跟一个固定的判断条件,在status判断前面加一个and -->
        <!--这种方式有弊端,如果所有的条件都不满足,会查询到所有的数据-->
        <!--<select id="selectByConditions" 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 LIKE CONCAT('%', #{companyName}, '%')
            </if>
            <if test="brandName!=null and brandName!=''">
                AND brand_name LIKE CONCAT('%', #{brandName}, '%')
            </if>
        </select>-->
        <!--使用where标签解决语法漏洞-->
        <!--<select id="selectByConditions" resultMap="brandResultMap">
            SELECT * FROM tb_brand
           <where>
               <if test="status!=null">
                   status = #{status}
               </if>
               <if test="companyName!=null and companyName!=''">
                   AND company_name LIKE CONCAT('%', #{companyName}, '%')
               </if>
               <if test="brandName!=null and brandName!=''">
                   AND brand_name LIKE CONCAT('%', #{brandName}, '%')
               </if>
           </where>
        </select>-->
        <!--trim标签解决语法漏洞-->
        <!--prefix="where"  trim里面的sql语句前面带一个where关键字-->
        <!--prefixOverrides="and|or"  trim里面的sql前面有多余的and或or关键字,就清楚这个关键字-->
        <!--<include refid="selectBrandSql"></include>   引入一段sql语句-->
        <select id="selectByConditions" resultMap="brandResultMap">
            <include refid="selectBrandSql"></include>
            <trim prefix="where" prefixOverrides="and|or">
                <if test="status!=null">
                    status = #{status}
                </if>
                <if test="companyName!=null and companyName!=''">
                    and company_name LIKE CONCAT('%', #{companyName}, '%')
                </if>
                <if test="brandName!=null and brandName!=''">
                    and brand_name LIKE CONCAT('%', #{brandName}, '%')
                </if>
            </trim>
        </select>
        <!--动态修改商品信息-->
        <!--下面的写法,当status为null的时候,会造成sql语句语法错误(结尾多了一个逗号)-->
        <!--<update id="updateBrand">
            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 brandName!=''">
                description=#{description},
            </if>
            <if test="status!=null ">
                status=#{status}
            </if>
            WHERE id = #{id};
        </update>-->
        <!--set标签-->
        <!--<update id="updateBrand">
            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>-->
        <!--trim-->
        <update id="updateBrand">
            UPDATE tb_brand
            <trim prefix="set" suffixOverrides="," suffix="WHERE id = #{id}">
                <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>
            </trim>
        </update>
    
        <!--批量删除-->
        <!-- <delete id="deleteByIds">
             delete FROM tb_brand WHERE  id in(11,12,13);
         </delete>-->
    
        <!--collection="数组或集合"  实际就是你参数的名字 如果没有在接口中指定参数名,使用默认的arg0参数名-->
        <!--item="id"  代表集合获数组中每一个数据-->
        <!--open  与之前语法连接的开始字符-->
        <!--close  与之后语法连接的结束字符-->
        <!--separator 多个数据之间的分割字符-->
        <!-- #{id}  里面的id原则上要与item="id"中的变量名一直-->
        <delete id="deleteByIds">
            DELETE
            FROM tb_brand
            WHERE id in
            <foreach collection="ids" item="id" open="(" close=")" separator=",">
                #{id}
            </foreach>
        </delete>
    </mapper>
    
  1. 注解完成增删改查 - 只能应对比较简单的SQL语句

    • 概述

    • 例子:查询 - 查看商品详情

    • 测试类

      public class MyBatisTest {
      
          private static SqlSessionFactory factory;
          private SqlSession sqlSession;
          private BrandDao brandDao;
      
          @BeforeClass
          public static void getSQLFactory() throws Exception {
              //获取核心文件输入流
              InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
              //获取工厂常见对象
              SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
              //获取工厂对象
              factory = builder.build(in);
          }
      
          @Before
          public void getSqlSession() {
              //获取会话对象
              sqlSession = factory.openSession();
              //获取代理对象
              brandDao = sqlSession.getMapper(BrandDao.class);
          }
      
      
          @Test
          public void testSelectAll() {
              List<Brand> brands = brandDao.selectAll();
              for (Brand brand : brands) {
                  System.out.println(brand);
              }
          }
      
          @After
          public void closeSqlSession() {
              //关闭资源
          }
      }
      
    • BrandDao.java

      public interface BrandDao {
      
          @Select(value = "select * from tb_brand")
          @ResultMap("brandResultMap")
              //@ResultMap(value = "brandResultMap")
          List<Brand> selectAll();
      }
      
    • BrandDao.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">
      <mapper namespace="com.itheima.dao.mapper.BrandDao">
          <resultMap id="brandResultMap" type="brand">
              <result column="brand_name" property="brandName"></result>
              <result column="company_name" property="companyName"></result>
          </resultMap>
      </mapper>
      
  2. 心得

    • 整型数据字段用Integer 类型,有助于处理null 的情况,因为从数据库中取数据有可能为空。

    • xml文件写SQL语句时,idea会校验是否正确,你可以在settings中关闭SQL dialect;或者把数据库连接中的 url 具体到要用的数据库。

    • resultMap 用于处理类的属性名与数据库中的字段名不一致的问题,因为不一致查出来会是 null。

    • ResultMap就是ResultType的高级写法,用了resultMap就不写resultType了。

    • Ctrl + Alt + F:把变量定义成全局变量。

    • 打印出不同编码的结果,修改引号里的编码方法即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值