MyBatis学习一

1.   MyBatis介绍

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

2.1.  流行的ORM框架java

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

2.Hibernate:目前最流行的ORM框架.设计灵巧,性能通常(本身去控制性能,不是很好控制),文档丰富.(彻底自动操做)面试

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

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

MyBatis 并非一个完整的ORM框架,由于咱们还须要本身去写所有SQLapache

2.2.  JDBC操做数据库缺陷安全

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

最大的缺点就是:session

   一、sql写在JAVA代码中改修改sql必须修改代码,须要从新编译。mybatis

   二、有不少重复性的操做(好比获取链接,释放资源等)

2.3.  ORM框架的操做数据库关系方式有不少种,经常使用的有两种    

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

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

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

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

 

2.4.  ORM框架工做原理

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

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

三、ORM经过对最原生jdbc的封装提供更加便利的操做API

四、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)的区别?
相关文章
相关标签/搜索