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)的区别?

 

posted @ 2019-07-20 19:03  龙龙鄂构  阅读(203)  评论(0编辑  收藏  举报