Mybatis第二部分

Posted by Cfeng on April 13, 2019

学习视频来自黑马程序员,感谢!

Mybatis和Hibernate 本质区别和应用场景

Hibernate:是一个标准ORM框架(对象关系映射),入门门槛较高,不需要写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难。
应用场景: 适用于需求变化不多的中小型项目:比如后台管理系统,arp,orm,oa (不过以基本淘汰)

Mybatis:专注sql本身,需要程序员自己编写sql语句,sql编写优化比较方便,是一个不完全的ORM框架。
应用场景: 需求变化较多的项目,比如:互联网项目。

Mybatis开发dao两种方法

SqlSession使用范围

  1. 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory。当成一个工具类,不需用单例管理。
  2. 通过SqlSessionFactory创建SqlSession,通过单例模式管理sqlSessionFactory
  3. SqlSession是一个面向用户的接口。提供了很多用于操作数据库的方法。 线程不安全,在SqlSession除了有接口中的方法,还有数据域属性。
    最佳应用场合在方法体内,定义成局部数据变量使用

原始dao开发方法

程序员需要写dao接口和实现类
需要向dao实现类中注入SqlSessionFactory ,在方法体内创建SqlSession

  1. dao接口
    public interface UserDao {
    //根据id查询
    public User findUserById(int id) throws Exception;
    //添加用户
    public void insertUser(User user) throws Exception;
    //删除用户
    public void deleteUser(int id) throws Exception;
    }
    
  2. dao实现类
    public class UserDaoImpl implements UserDao {
     private SqlSessionFactory sqlSessionFactory;
     public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
         this.sqlSessionFactory = sqlSessionFactory;
     }
     @Override
     public User findUserById(int id) throws Exception {
         SqlSession sqlSession = sqlSessionFactory.openSession();
         User user = sqlSession.selectOne("test.findUserById",1);
         sqlSession.close();
         return user;
     }
    }
    
  3. 原始dao开发问题总结
  • dao接口实现类方法中存在大量模版方法,设想能否将代码q提取出来,减轻程序员工作量
  • 调用sqlSession方法时,将statement的id硬编码
  • 由于sqlSession方法传入变量使用泛型,所以即使变量传入错误,在编译阶段也不报错,不利于程序员开发

Mybatis对mapper代理开发方法

只需要mapper接口(相当于dao接口)

  1. 思路
    • 程序员只需要编写mapper接口
    • 编写mapper.xml映射文件,只需遵循一些开发规范,Mybatis可以自动生成mapper接口实现类的代理对象
    • 在SqlMapConfig.xml配置。

    开发规范:

    • mapper.xml 中 namespace等于mapper接口地址
    • mapper接口中的方法名和mapper.xml中statement的id一致
    • mapper接口中方法输入参数类型,与xml中parameterType一致
    • mapper接口中方法返回值类型,与xml中resultType一致

总结: 以上开发规范主要是对下边的代码进行统一生成:

User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);
......

小结

  1. 代理对象内部调用selectOne或selectList
    如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。
    如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。

  2. mapper接口方法参数只能有一个是否影响系统 开发 mapper接口方法参数只能有一个,系统是否不利于扩展维护。
    系统 框架中,dao层的代码是被业务层公用的。
    即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
    注意:持久层方法的参数可以包装类型、map。。。,service方法中建议不要使用包装类型(不利于业务层的可扩展)。

Mybatis配置文件

mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:

  • properties(属性)
  • settings(全局配置参数)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境集合属性对象)
  • environment(环境子属性对象)
  • transactionManager(事务管理)
  • dataSource(数据源)
  • mappers(映射器)

properties(属性)

需求:
将数据库连接参数单独配置在dp.properties中,只需要在SqlMapConfig.xml加载属性值。在SqlMapConfig.xml中就不需要对数据库连接参数硬编码。 将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,其它xml可以引用该db.properties。
db.properties。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&useSSL=true
jdbc.username=root
jdbc.password=******

加载属性文件

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

注意: MyBatis 将按照下面的顺序来加载属性:

  1. 在 properties 元素体内定义的属性首先被读取。
  2. 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
  3. 最后读取parameterType传递的属性,它会覆盖已读取的同名属性。

建议:
不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。 在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX

settings (全局配置参数)

mybatis框架在运行时可以调整一些运行参数。
比如:开启二级缓存、开启延迟加载。
全局参数将会影响mybatis的运行行为。

typeAliases(类型别名)

  1. 需求 在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。
    如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
    有默认别名,详情谷歌
<typeAliases>
    针对单个别名定义
    type:类型的路径
    alias:别名
    
    <typeAlias type="com.caoerzhe.po.User" alias="user"/>
    批量别名定义
    指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
    <package name="com.caoerzhe.po"/>
    
</typeAliases>

typeHandlers(类型处理器)

mybatis中通过typeHandlers完成jdbc类型和java类型的转换。
通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.

mappers(映射器)

  1. 通过resource方法一次加载一个映射文件
  2. 通过mapper接口加载单个 映射文件
  3. 批量加载mapper
<mappers>
    通过resource方法一次加载一个映射文件
    <mapper resource="mapper/UserMapper.xml"/>
    
    通过mapper接口加载单个 映射文件
    遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
    上边规范的前提是:使用的是mapper代理方法
    
    mapper class="com.caoerzhe.mapper.UserMapper"/>

    批量加载mapper
    指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
    遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
    上边规范的前提是:使用的是mapper代理方法
   
    <package name="com.caoerzhe.mapper"/>
</mappers>

注意:maven项目的约定配置文件必须放resources里,src目录下的xml文件默认不会编译到target,所以无法使用后两种方法