zoukankan      html  css  js  c++  java
  • MyBatis学习一

    1.   MyBatis介绍

    • 1.  MyBatis完成CRUD(掌握)
    • 2.  MyBatis的核心对象(掌握)
    • 3. MyBatis使用细节(掌握)
    1. ORM概述

    2.1.  流行的ORM框架

    1.JPA:本身是一种ORM规范,不是ORM框架.由各大ORM框架提供实现.

    2.Hibernate:目前最流行的ORM框架.设计灵巧,性能一般(自己去控制性能,不是很好控制),文档丰富.(完全自动操作)

    Hibernate是一个完整的ORM框架,常规CRUD我们不需要写一句SQL;

    3.MyBatis:本是apache的一个开源项目iBatis,提供的持久层框架包括SQL Maps和Dao,允许开发人员直接编写SQL(更好灵活).(Sql操作方式)

    MyBatis 并不是一个完整的ORM框架,因为我们还需要自己去写全部SQL

    2.2.  JDBC操作数据库缺陷

    首先,通过jdbc也能实现对象实体和数据库关系的映射.那就是采用硬编码方式,为每一种可能的数据库访问操作提供单独的方法。 也就是各种Dao(UserDao DeptDao等)。

    最大的缺点就是:

       1、sql写在JAVA代码中改修改sql必须修改代码,需要重新编译。

       2、有很多重复性的操作(比如获取连接,释放资源等)

    2.3.  ORM框架的操作数据库关系方式有很多种,常用的有两种    

    2.3.1.   Sql操作方式(对jdbc进行封装)(mybatis的实现方式)

            把SQL配置到配置文件中,通过不同SQL中完成对象实体和数据库关系相互转换的操作。

    2.3.2.   完整操作(JPA、Hibenate实现方式)

           直接映射的是对象实体和数据库关系映射。操作数据库关系,不用写SQL由框架自己生成。

     

    2.4.  ORM框架工作原理

    1、以一定的映射方式,把实体模型和数据库关系的映射

    2、ORM框架启动时加载这些映射和数据库配置文件

    3、ORM通过对最原生jdbc的封装提供更加便利的操作API

    4、Dao通过ORM提供的便捷API以对象的方式操作数据库关系。

     

    1. MyBatis的认识

    3.1.  MyBatis的起源

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。

    2013年11月迁移到Github。

    iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。

    iBATIS提供的持久层框架包括SQL Maps(XML映射配置)和Data Access Objects(Dao)

    3.2.  MyBatis的介绍

    MyBatis 是一个支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。

    MyBatis 消除了几乎所有的JDBC代码和手工设置参数以及结果集的检索。

    MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

    MyBatis不能自动创建表,如果能够自动建表,必须自己先准备好建表的sql语句。

    1. MyBatis完成CRUD

    4.1.  操作前的准备工作

    创建一个java项目?略过

    4.1.1.   导入相应的9个jar包

    MyBatis是一个框架,咱们说了。在Java中框架就是一组Java类最后打成jar包。因此,不只是这个框架,以后咱们学习的所有框架。在使用前都要先导入相应 的jar包。

    在导入jar包之前,我们得先说一下,MyBatis是操作数据库的框架。咱们以前学JDBC的时候说过:要操作数据库,一定不要忘了导入相应的数据库驱动包。

      注:驱动包就是各大数据库厂商根据JDBC规范实现的jar包(忘了的同学可以去看JDBC第一天的笔记)

     

    然后找到MyBatis(相关文件我们已经准备好,大家也可以到网上进行自行下载),再导入MyBatis的核心包与依赖包。

    下图为我们使用MyBatis要导入的包:

     

     

    4.1.2.   准备相应的表

    咱们对数据库进行操作,肯定需要准备表。这没啥好说的。

    现在直接引入我们准备好的product表即可:

     

     

     

    4.1.3.   准备相应的domain

    创建一个Product对象,和数据库的表对应

    注:类的名称和类型都和我们的product表相对应匹配

    public class Product {

             private       Long id;

             //商品名称

             private String productName;

             //品牌

             private String brand;

             //供应商

             private String supplier;

             //零售价

             private Double salePrice;

             //进价

             private Double costPrice;

             //折扣比例

             private Double cutoff;

             //商品分类编号

             private Long dir_id;

              

       //提供getter与setter...

    }

    4.2.  小结

    准备步骤:

    1 导包

    2 建表(product)

    3 domain(Product)

    4 准备dao层(CRUD)

    5 测试(不是必需的)

    注意:我们要引哪些包?

    1 一定要引入驱动包(不要忘了)

    2 导入mybatis的核心包

    3 导入mybatis的依赖包

    4.3.  product的Dao层准备

    /**

     * 商品的持久操作

     */

    public interface IProductDao {

             /**

              * 添加一个商品

              */

             void save(Product p);

            

             /**

              * 更新一个商品

              */

             void update(Product p);

            

             /**

              * 删除一个商品

              */

             void delete(Long id);

            

             /**

              * 得到一个商品

              */

             Product get(Long id);

             /**

              * 得到所有商品

              */

             List<Product> getAll();

    }

    1. MyBatis核心配置文件

    5.1.  看文档

    一切准备就绪。接下来就是开始使用MyBatis了。但是问题来了,怎么用呢?

    该文档虽然只有50多页,但是已经足够咱们学习了。

    先来入个门吧:入门开始,除了介绍什么是MyBatis之后,就在说一个核心对象:SqlSessionFactory,接下来,咱们就是要想方设法拿到这个核心对象。

        那SqlSessionFactory对象怎么拿到:直接找到文档中的从 XML 中构建 SqlSessionFactory这一小节开始即可。

    5.2.  从这一节中我们可以看出以下几个点:

        1 我们需要准备一个核心的xml文件

        2 拿到SqlSessionFactory之前需要读取核心的xml配置文件

        3 需要构造者(SqlSessionFactoryBuilder)来创建它

    5.3.  MyBatis-Config.xml

        好了,大概介绍完毕后,我们可以开始准备核心配置的xml文件了

        在资源文件夹下面创建一个文件,取名为MyBatis-Config.xml

        以把文档中的配置拷备过来(先做了解测试,等功能可以用起来后,再自己去写这个配置)

    5.4.  配置MyBatis-Config.xml提示信息

     

    5.5.  核心配置的一个简单介绍:

    我们需要准备几个东西需要一个环境environments

    environments 里面两个内容(transactionManager ,dataSource )

    dataSource : driver,url,username,password(连接数据库的最小单位)

    <configuration>

             <!-- 环境们 (很多环境的意思)

                      default:默认使用哪一个环境(必需对应一个环境的id)

              -->

             <environments default="development">

                      <!--

                               一个环境  id:为这个环境取唯一一个id名称

                      -->

                      <environment id="development">

                               <!-- 

                                        事务管理   type:JDBC(支持事务)/MANAGED(什么都不做)

                               -->

                               <transactionManager type="JDBC" />

                               <!-- 数据源, 连接池  type(POOLED):MyBatis自带的连接池 -->

                               <dataSource type="POOLED">

                                        <!-- 连接数据库的参数 -->

                                        <property name="driver" value="com.mysql.jdbc.Driver" />

                                        <property name="url" value="jdbc:mysql:///mydb" />

                                        <property name="username" value="root" />

                                        <property name="password" value="admin" />

                               </dataSource>

                      </environment>

             </environments>

       <!-- 这个mappers代表的是相应的ORM映射文件 -->

             <mappers>

                      <mapper resource="cn/itsource/domain/ProductMapper.xml" />

             </mappers>

     

    </configuration>

    5.6.  抽取数据库信息配置文件

    现在咱们的关于数据库连接信息已经在配置文件(XML)中,但是更多时候,我们还是会把配置文件的信息放到db.properties中。(由于properties的结构简单,便于修改,而这个文件只放数据库的连接信息也更好的体现了职责分离)。

    其实,在官方文档的核心文件配置,直接就是使用的推荐properties的方式

    只需要我们做如下修改即可:

    5.6.1.   MyBatis-Config.xml

    <configuration>

             <!-- 引入Properties文件 -->

             <properties resource="db.properties"></properties>

             <environments default="development">

                      <environment id="development">

                               <transactionManager type="JDBC" />

                               <dataSource type="POOLED">

                                        <!-- 根据key拿到properties中的value值 -->

                                        <property name="driver" value="${db.driver}" />

                                        <property name="url" value="${db.url}" />

                                        <property name="username" value="${db.username}" />

                                        <property name="password" value="${db.password}" />

                               </dataSource>

                      </environment>

             </environments>

             <mappers>

                      <mapper resource="cn/itsource/domain/ProductMapper.xml"/>

             </mappers>

    </configuration>

    5.6.2.   db.properties

    db.driver=com.mysql.jdbc.Driver

    db.url=jdbc:mysql:///test0303

    db.username=root

    db.password=admin

    5.7.  映射文件

    核心文档已经搭建准备就绪,心里还有一点小激动。

    但是总是觉得,少了点什么? 是什么呢?

    请大家回顾与分析我们刚才学习的内容:

    MyBatis是一个ORM映射框架,请问ORM体现在哪?

    核心文件中有一个mappers,它指向了一个映射文件。映射文件在哪?

    不是说好的MyBatis要写SQL语句么?SQL语句又在哪里?

    一切的一切都会出现在我们的下一个章节:对象与关系的映射!敬请关注。

     

    现在直接写xml是没有提示了,在xml的约束中,咱们讲过,当有约束的时候,xml就会有提示。

           提示:出门再拐 在xml那一章的schema与dtd约束

    而现在咱们的约束是在网络上。在Eclipse中,我们可以找到相应的约束文件,然后配置到自己本地即可。

    5.8.  对象与关系的映射(ORM)

    接下来,解决上一章的几个问题。

    直接找到我们文档中的探究已映射的SQL语句,在这里,我就可以看到一段xml(如下图),这个xml就是咱们需要的映射文件,它就可以体现出ORM,并且在这里面,也可以愉快的写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的主要功能就是写sql

             mapper:根

             namespace:命令空间 (用来确定唯一) 以前这个是可以不加的,现在必需加

         namespace的值,规则的:映射文件XxxMapper.xml所在的包+domain类名+Mapper

     -->

    <mapper namespace="cn.itsource.mybatis.day1._1_hello.ProductMapper">

             <!--

                      select : 这里面写查询语句

                      id:用来确定这条sql语句的唯一

                                  以后我们确定唯一,也就是找sql语句 : namespace +.+ id

                                例: cn.itsource.mybatis.day1._1_hello.ProductMapper.get

                      parameterType : 传入的参数类型  long:大Long  _long:小long (具体的对应请参见文档)

                      resultType : 结果类型(第一条数据返回的对象类型) 自己的对象一定是全限定类名

              -->

             <select id="get" parameterType="long" resultType="cn.itsource.domain.Product">

                      select * from product where id = #{id}

             </select>

    </mapper>

    5.9.  在上述文件中,希望大家注意几个规范:

    ① 我们的映射文件一般情况下是和它对应的domain实体类在同一个层级

    ② 这个映射文件的名称一般叫做 XxxMapper.xml (Xxx代表的是实体类名称)

    ③ namespace的名称为了确定唯一性,请大家根据我的要求取名

        如我们有一个类:

        cn.itsource.domain.Product / cn.itsource.domain.Student

        那这里取名应该是:

        cn.itsource.domain.ProductMapper /cn.itsource.domain.StudentMapper

    ④ 除了MyBatis支持的类型,其它的类型都通通使用全限定名   

    1. 完成数据的CRUD

    核心文件有了,映射文件也有了。现在可以来完成咱们的CRUD了吧!

    但是应该从哪里开始好呢?

    还记得咱们前面说过需要的核心对象SqlSessionFactory吧

    咱们说过,需要通过它去拿到一个SqlSession对象(相当于JDBC的连接)

    必需要有SqlSession这个对象,我们才可以去执行相应的Sql

    6.1.  拿到SqlSession对象

    官方文档从XML 中构建 SqlSessionFactory这一章中,除了配置的核心xml,在上面我们还可以看到几句代码(如下图),现在咱们就来详细分析一下这几句代码是什么意思:

     

     

     我们简单解释一下上面的代码:读取核心文件,然后再通过SqlSessionFactoryBuilder构建者来创建一个SqlSessionFactory工厂。

    注:上面的sqlMapper其实是一个SqlSessionFactory工厂对象(它取名不是很直观)

     

    官方文档从SqlSessionFactory 中获取 SqlSession这一章中,我们可以看到代码(下图),然后再拿到SqlSession,并且在这里面,还附上了咱们怎么调用sql的代码。

    6.2.  工具类的抽取MyBatisUtils

    对于MyBatis的工具类抽取,咱们直接使用静态工具的单例模式。

    注:几种单例模式的区别与使用(单例工具与静态工具的区别),大家可以去看基础加强那天的课程。

     

    import java.io.Reader;

     

    import org.apache.ibatis.io.Resources;

    import org.apache.ibatis.session.SqlSession;

    import org.apache.ibatis.session.SqlSessionFactory;

    import org.apache.ibatis.session.SqlSessionFactoryBuilder;

     

    public class MyBatisUtils {

             // 保证SqlSessionFactory是单例

             private static SqlSessionFactory sqlSessionFactory;

     

             // SqlSessionFactory类似于JPA的EntityManagerFactory,Hibernate的SessionFactory

             // SqlSession 类似于JPA的EntityManager,Hibernate的Session

     

             static {

                      try {

                               Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");

                               sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

                      } catch (Exception e) {

                               e.printStackTrace();

                               throw new RuntimeException("解析MyBatis的配置文件或者映射文件出现异常:" + e.getMessage());

                      }

             }

     

             // 对外提供一个类

             public static SqlSession getSession() {

                      return sqlSessionFactory.openSession();

             }

    }

     

    6.3.  查询一条数据

    根据上面我们get到的技能,使用MyBatis查询一条数据!

     

     

    大家要注意咱们传过去的参数,还有在SQL接收的参数!【课堂分析】

    传过去的变量名称和#里面的字符串名称不是一回事!

     

    讲到这里,咱们再对整个MyBatis的流程再进行一次分析。

    ①:我们需要核心文件(提供联系数据库的环境)

    ②:需要映射文件(提供ORM与运行的SQL语句)

    ③:拿到SqlSession对象,用于执行SQL

    @Override

    public Product get(Long id) {

             SqlSession sqlSession = null;

             try {

                      sqlSession = MyBatisUtils.getSession();

                      return sqlSession.selectOne(NAME_SPACE + "get", id);

             } catch (Exception e) {

                      e.printStackTrace();

                      throw new RuntimeException("ProductDaoImpl.get出现异常:" + e.getMessage());

             } finally {

                      if (sqlSession != null) {

                               sqlSession.close();

                      }

             }

    }

    6.4.  junit来一个测试(必须的)

    写代码要测试,这是一个好习惯!

    public class ProductDaoTest {

     

             IProductDao productDao = new ProductDaoImpl();

     

             @Test

             public void testGet() {

                      Product product = productDao.get(1L);

                      System.out.println(product);

             }

     

    }

    6.5.  查询所有数据

    6.5.1.   代码

    @Override

    public List<Product> getAll() {

             SqlSession sqlSession = null;

             try {

                      sqlSession = MyBatisUtils.getSession();

                      return sqlSession.selectList(NAME_SPACE + "getAll");

             } catch (Exception e) {

                      e.printStackTrace();

                      throw new RuntimeException("ProductDaoImpl.get出现异常:" + e.getMessage());

             } finally {

                      if (sqlSession != null) {

                               sqlSession.close();

                      }

             }

    }

    6.5.2.   映射文件

    <!-- 返回类似仍然是Product:domain类 -->

    <select id="getAll" resultType="cn.itsource.mybatis.day1._1_hello.Product">

             select * from product

    </select>

    6.5.3.   测试

    @Test

    public void testGetAll() {

             List<Product> list = productDao.getAll();

             for (Product product : list) {

                      System.out.println(product);

             }

    }

    6.6.  添加一条数据

    注:添加的时候一定要记住提交事务(配置事务、表结构支持事务)

    JDBC的事务是自动提交的,而JPA、Hibernate、MyBatis事务都是需要手动提交的

    6.6.1.   代码

    @Override

    public void save(Product product) {

             SqlSession sqlSession = null;

             try {

                      sqlSession = MyBatisUtils.getSession();

                      sqlSession.insert(NAME_SPACE + "save", product);

                      // JDBC的事务是自动提交的,而JPA、Hibernate、MyBatis事务都是需要手动提交的

                      sqlSession.commit();

             } catch (Exception e) {

                      e.printStackTrace();

                      throw new RuntimeException("ProductDaoImpl.get出现异常:" + e.getMessage());

             } finally {

                      if (sqlSession != null) {

                               sqlSession.close();

                      }

             }

    }

    6.6.2.   映射文件

    <!-- void save(Product product); -->

    <insert id="save" parameterType="cn.itsource.mybatis.day1._1_hello.Product">

             <!-- #{productName}==product.getProductName() -->

             insert into product(productName,salePrice,costPrice,cutoff,supplier,brand,dir_id)

             values

             (#{productName},#{salePrice},#{costPrice},#{cutoff},#{supplier},#{brand},#{dir_id})

    </insert>

    6.6.3.   测试

    @Test

    public void testSave() {

             Product product = new Product();

             product.setBrand("大力牌");

             product.setCostPrice(30.0);

             product.setCutoff(0.8);

             product.setDir_id(1L);

             product.setProductName("000000");

             product.setSalePrice(60D);

             product.setSupplier("东莞供应商");

             productDao.save(product);

    }

    添加数据的有时候咱们需要拿到当前数据的主键。咱们先移步到MyBatis细节一章的拿到返回主键部分!

     

    6.7.  修改一条数据

    6.7.1.   代码

    @Override

    public void update(Product product) {

             SqlSession sqlSession = null;

             try {

                      sqlSession = MyBatisUtils.getSession();

                      sqlSession.update(NAME_SPACE + "update", product);

                      // JDBC的事务是自动提交的,而JPA、Hibernate、MyBatis事务都是需要手动提交的

                      sqlSession.commit();

             } catch (Exception e) {

                      e.printStackTrace();

                      throw new RuntimeException("ProductDaoImpl.get出现异常:" + e.getMessage());

             } finally {

                      if (sqlSession != null) {

                               sqlSession.close();

                      }

             }

    }

    6.7.2.   映射文件

    <!-- void update(Product product); -->

    <update id="update" parameterType="cn.itsource.mybatis.day1._1_hello.Product">

             <!-- #{productName}==product.getProductName() -->

             update product set productName=#{productName},salePrice=#{salePrice},costPrice=#{costPrice},

             cutoff=#{cutoff},supplier=#{supplier},brand=#{brand},dir_id=#{dir_id}

             where id=#{id}

    </update>

    6.7.3.   测试

    @Test

    public void testUpdate() {

             Product product = productDao.get(1L);

             System.out.println(product);

            

             product.setBrand("大力牌");

             product.setCostPrice(30.0);

             product.setCutoff(0.8);

             product.setDir_id(1L);

             product.setProductName("000000");

             product.setSalePrice(60D);

             product.setSupplier("东莞供应商");

             productDao.update(product);

            

             product = productDao.get(1L);

             System.out.println(product);

    }

     

     

    6.8.  删除一条数据

    6.8.1.   代码

    @Override

    public void delete(Long id) {

             SqlSession sqlSession = null;

             try {

                      sqlSession = MyBatisUtils.getSession();

                      sqlSession.delete(NAME_SPACE + "delete", id);

                      // JDBC的事务是自动提交的,而JPA、Hibernate、MyBatis事务都是需要手动提交的

                      sqlSession.commit();

             } catch (Exception e) {

                      e.printStackTrace();

                      throw new RuntimeException("ProductDaoImpl.delete出现异常:" + e.getMessage());

             } finally {

                      if (sqlSession != null) {

                               sqlSession.close();

                      }

             }

    }

    6.8.2.   映射文件

    <!-- void delete(Long id); -->

    <delete id="delete" parameterType="id">

             delete from product where id=#{id}

    </delete>

    6.8.3.   测试

    @Test

    public void testDelete() {

             productDao.delete(1L);

             Product product = productDao.get(1L);

             System.out.println(product);

    }

    6.9.  CRUD注意事项

    下面的点都很重要,是大家在使用MyBatis的时候经常出现的点。希望大家引起重视。出现问题的时候过来好好的来找。基本咱们使用MyBatis中出的错都在这里。

    使用框架的时候配置信息变多,在配置里写的都是字符串,而且经常是要对应的。因为,这里希望大家要切记:写的时候细心,出现错误找字符串要耐心,

    1 主配置中未配置相应的mapper(当然,这个路径也可能写错)

    2 在代码中调用Sql的时候路径写错

    3  Sql写错,这个应该还好找

    4 当我们在配置文件中很多地方如果写错,即便是你还没有使用也可能会报错

    5 写Sql的标签不需要全部一致(如添加不一定必需使用insert),但是它的属性会不同

    6 在传入与返回参数时全限定类名写错

     

        在开发的时候,要边做边测试。 在某一步出现错误后,删除新加的代码看有没有问题,如果删除部分代码后运行成功,就相应的可以缩小排错的范围。

    1. MyBatis三大核心对象

    SqlSessionFactory类似于JPA的EntityManagerFactory,Hibernate的SessionFactory

    SqlSession 类似于JPA的EntityManager,Hibernate的Session

    详细的认识一下MyBatis的几个核心类:

    7.1.  SqlSessionFactoryBuilder

    建造者模式:我们最后拿到的这个对象是非常复杂的. 用这个建造者就它先为我们把这些复杂的代码完成.

      这个类可以被实例化,使用和丢弃。一旦你创建了SqlSessionFactory后,这个SqlSessionFactoryBuilder类就不需要存在了。因此SqlSessionFactoryBuilder实例的最佳范围是方法范围(也就是本地方法变量)。

    你可以重用SqlSessionFactoryBuilder来创建多个SqlSessionFactory实例,但是最好的方式是

    不需要保持它一直存在来保证所有XML解析资源,因为还有更重要的事情要做。

    7.2.  SqlSessionFactory

     一旦被创建,SqlSessionFactory应该在你的应用执行期间都存在。没有理由来处理或重新创建它。使用SqlSessionFactory的最佳实践是在应用运行期间不要重复创建多次。这样的操作将被视为是非常糟糕的。因此SqlSessionFactory的最佳范围是应用范围。

    有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。然而这两种方法都不认为是最佳实践。这样的话,你可以考虑依赖注入容器,比如Google Guice或Spring。这样的框架允许你创建支持程序来管理单例SqlSessionFactory的生命周期。

    7.3.  SqlSession

    每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的。因此最佳的范围是请求或方法范围。

    绝对不能将SqlSession实例的引用放在一个类的静态字段甚至是实例字段中。

    也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet架构中的HttpSession。

    如果你现在正用任意的Web框架,要考虑SqlSession放在一个和HTTP请求对象相似的范围内。换句话说,基于收到的HTTP请求,你可以打开了一个SqlSession,然后返回响应,就可以关闭它了。关闭Session很重要,

    为什么在这里我们要先说这三大核心对象呢,因为在我们必需要了解这三个对象的特性。才可以更好的根据这个特性来完成工具类代码。

    1. MyBatis的使用细节

    8.1.  添加时拿到返回的主键

    注:若是忘了为什么要拿到主键。可以去看JDBC第二天的课程,那里咱们当时有详细的解释。

     

             <!--

                      parameterType:需要传入我们的对象

                      useGeneratedKeys: 是否需要主键

                      keyColumn:主键所在的列,可以不用配置

                      keyProperty:对象中的属性(代表主键的那个属性)

              -->

             <insert id="save" parameterType="cn.itsource.domain.Product"

                               useGeneratedKeys="true"

                               keyColumn="id"

                               keyProperty="id"

                      >

                      insert into product (productName,dir_id,salePrice,supplier,brand,cutoff,costPrice)

                               values (#{productName},#{dir_id},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})

             </insert>

    主键就直接放到返回的对象里面

    8.2.  Log4j日志框架

    在使用MyBatis的很多时候,我们需要把日志打印出来,帮助我们进行分析与排错。特别是大家现在学习阶段,要求大家都MyBatis的日志打开。

    打开后我们可以看到执行的SQL语句,可以看到我们传递的参数。

    而MyBatis中打印日志使用的是Log4j

    8.2.1.   Log4j简介:

    Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局)。

    可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。

    8.2.2.   日志等级

    等级从低到高

    TRACE:详细

    Debug:调试,类似于System.out.print

    Info:信息,类似于JPA打印sql等级

    Warn:警告,程序可以正常运行,出现提示

    Error:错误,出现异常

    8.2.3.   log4j.properties

    要在项目中打开日志,大家在资源文件根目录下创建一个log4j.properties的文件,并把下面的代码拷备到里面。

    log4j.properties(日志文件:)

    log4j.rootLogger=ERROR, stdout

    #log4j.rootLogger=NONE

    log4j.logger.cn.itsource=TRACE   把左边包名改成你自己的包名

     

    log4j.appender.stdout=org.apache.log4j.ConsoleAppender

    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

    log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

    注意:在上面的标红部分是我们需要修改的,它大概表示为当前会打印哪些位置下面文件的日志。

    cn.itsource:一定要根据自己的包名情况进行修改

        如果配置成功,那么在MyBatis运行操作数据时就可以看到相应的日志了。

    8.3.  MyBatis中为一个类取别名

    别名:分两种

    8.3.1.   内置别名

     

    8.3.2.   自定义别名

    在我们前面传参与接收结果的时候,咱们一直是使用的全限定名。

    但是MyBatis自己在使用很多类型的时候(如Integer,Boolean)却可以直接使用别名。

    那么,咱们自己的写的类能不能使用别名呢?

    大家可以直接找到官文文档上typeAliases这一章,有介绍我们怎么为自己的类取别名。

    取别名有什么用,呵呵。我认识一个朋友,他叫做:特雷西.麦克格雷迪,我叫他麦迪

     

    下面为取别名的代码:

    <typeAliases>

                      <!--

                               将一个包下面的所有类都取上别名:<package name="cn.itsource.domain" />

                               alias:取的别名

                               type:这个别名所对应的Java类

                                        :别名使用的时候与大小写无关

                       -->

    <typeAlias alias="product" type="cn.itsource.domain.Product" />

    <!-- 做项目的时候使用 -->

    <package name="cn.itsource.mybatis.day1._2_detail" />

    </typeAliases>

     

    注:必需在主文件中设置别名,其它地方才可以使用(切记切记)

    8.4.  列名与属性名不对应的解决方案resultMap

        原来通过javaBean自动映射,可以使用手动映射

    大家应该有注意到,前面咱们做映射文件的时候,只做了表与对象之间的联系。并没有做列与字段之间的联系。那么它们之间是怎么联系上的呢?

    由于之前咱们的列名与属性名是一样的,因此框架进行了自动的识别。

    那么:如果咱们的列名与属性名不一致了(对应不上),这时候应该怎么办呢?

    这时候,就需要我们开发人员告诉MyBatis,我们需要把哪些列名与属性名对应上。

     

    在MyBatis中,提供了一个resultMap的标签,就是让咱们来完成返回结果的关系对应的,使用方式如下:

     

    <!--

             返回的数据映射

                      type:代表是要映射的对象

                      id:代表唯一(过会我们要拿到它)

    -->

    <resultMap type="cn.itsource.domain.Product" id="productMap">

             <!--

                      column:对应的列名

                      property:对应的属性名

              -->

             <id column="id" property="id"  />

             <result column="productName" property="name" />

    </resultMap>     

     

    <select id="queryOne" parameterType="long" resultMap="productMap">

             select * from product where id = #{id}

    </select>

    1. 课程总结

    9.1.  重点

    1. MyBatis CRUD

    9.2.  难点

    1. 怎样获取主键,怎样配置
    2. Log4j理解
    3. 别名
    4. 常见异常
    5. java.lang.ClassNotFoundException: Cannot find class: id

    <delete id="delete" parameterType="id">应该传入long类型,而不是id

    1. Caused by: org.xml.sax.SAXParseException; lineNumber: 23; columnNumber: 4; 元素类型 "select" 必须由匹配的结束标记 "</select>" 终止。

    <select id="getAll" resultType="cn.itsource.mybatis.day1._1_hello.Product">

             select id,productName,salePrice,costPrice,cutoff,supplier,brand,dir_id from

             product

    </insert>

    1. Caused by: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.itsource.mybatis.day1._1_hello.ProductMapper.get

    没有配置文件里面加载映射文件,如何开始就使用

    1. Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'productName' in 'class cn.itsource.mybatis.day1._2_detail.Product'

    Product类里面没有'productName'属性

    1. 常见问题
    2. 没有导入数据库的驱动包
    3. 在XML中很多都是字符串,细心,不要写错
    4. 在映射文件中全限定类名可能会写错
    5. 找不到相应的Statement(sql语句)
    6. 找SQL的Statement写错了
    7. 在核心XML中没有找相应的映射文件
    8. 在我们调用Statement(sql语句的时候),经常会忘记传参
    9. 执行成功后,数据库却没有反映,很有可能是没有提交事务
    10. 可能我们忘了写执行的代码了
    11. 错误一定要打印出来(执行的时候没效果,但是又不报错)
    12. Mapper中就算一个语句没有使用,它的错也可能会影响到其它正确的语句
    13. 框架的错往往从后向前找
    14. 很多同学没有取别名,但是他一直去用
    15. Mysql乱码,添加字符编码:useUnicode=true&amp;characterEncoding=UTF-8

     

    1. 课后练习
    2. 面试题
    3. mybatis相较于jdbc的优点?

    把sql语句从java代码中抽取出来,方便维护。并且修改sql时不用修改java代码

    不用手动设置参数和对结果集的处理。

    1. 扩展知识或课外阅读推荐

    14.1.         扩展知识

    1. 以后工作是用JPA(Hibernate)还是用MyBatis呢?

     

    1. MyBatis与JPA(Hibernate)的区别?

     

  • 相关阅读:
    linux学习笔记(十四)
    linux学习笔记(十三)
    linux学习笔记(十二)
    linux学习笔记(十一)
    linux学习笔记(十)
    linux学习笔记(九)
    linux学习笔记(八)
    linux学习笔记(七)
    linux学习笔记(六)
    linux学习笔记(五)
  • 原文地址:https://www.cnblogs.com/Src-z/p/11218843.html
Copyright © 2011-2022 走看看