zoukankan      html  css  js  c++  java
  • mybatis第一天

     

    Mybatis框架课程

     

    第一天

    1. 课程计划

    第一天:(入门)

    1、原生Jdbc操作数据库存在的问题总结

    2、Mybatis介绍架构原理

    3、Mybatis入门程序(Crud

    a) Mybatis QuickStart

    b) Mybatis入门详解

    4、Mybatis的两种Dao开发方式

    a) 原始Dao开发方式

    b) Mapper动态代理开发方式

    5、Mybatis全局配置文件SqlMapConfig.xml说明

    6、MybatisHibernate区别

    第二天:(高级应用)

    1、输入映射和输出映射

    a) 输入参数映射

    b) 返回值映射

    2、动态Sql

    3、关联对象映射

    a) Association(关联单个对象,即一对一)

    b) Collection(关联集合,即一对多)

    4、Mybatis整合Spring

    5、Mybatis逆向工程

    2. 原生Jdbc操作数据库存在的问题总结

    2.1. 创建Mysql数据库

    创建数据库,数据库名:mybatis

    将下图所示Sql脚本在数据库中执行,初始化测试数据

     

    n 效果如下图:

    2.2. 编写JDBC程序

    2.2.1. 创建工程

    n 开发环境:

    IDEEclipse Mars 2

    JDK1.7

    创建一个Java工程

    按下图进行创建

    需要Mysql 的数据库驱动,如下图Jar包。

    2.2.2. 原生Jdbc编程步骤

    1、 加载数据库驱动

    2、 创建并获取数据库链接

    3、 设置Sql语句

    4、 创建Jdbc Statement对象

    5、 设置Sql语句中的参数(使用PreparedStatement)

    6、 通过Statement执行Sql并获取结果

    7、 Sql执行结果进行解析处理

    8、 释放资源(ResultSetPreparedstatementConnection)

    2.2.3. 原生Jdbc程序

    public static void main(String[] args) {

    Connection connection = null;

    PreparedStatement preparedStatement = null;

    ResultSet resultSet = null;

    try {

    // 1、加载数据库驱动

    Class.forName("com.mysql.jdbc.Driver");

    // 2获取数据库链接

    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");

    // 3定义sql语句 ?表示占位符

    String sql = "select * from blog where author = ?";

    // 4获取预处理statement

    preparedStatement = connection.prepareStatement(sql);

    // 5设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值

    preparedStatement.setString(1, "张三");

    // 6向数据库发出sql执行查询,查询出结果集

    resultSet = preparedStatement.executeQuery();

    // 7、解析处理结果集

    while (resultSet.next()) {

    System.out.println(resultSet.getString("id") + "  " + resultSet.getString("author"));

    }

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    // 8释放资源

    if (resultSet != null) {

    try {

    resultSet.close();

    } catch (SQLException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    if (preparedStatement != null) {

    try {

    preparedStatement.close();

    } catch (SQLException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    if (connection != null) {

    try {

    connection.close();

    } catch (SQLException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

    上边使用原生Jdbc方法(未经封装)实现了查询数据库表记录的操作。

    2.3. 原生Jdbc问题总结

    1、 频繁创建、释放数据库连接造成系统资源浪费,影响系统性能。使用数据库连接池技术可以解决此问题

    2、 Sql语句写在代码中造成代码不易维护,实际应用中Sql变化的可能较大,Sql变动需要改变Java代码。

    3、 Sql语句传参数麻烦,因为Sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

    4、 结果集解析麻烦(列名硬编码),Sql变化会导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成Pojo对象解析比较方便。

    3. Mybatis介绍架构原理

    3.1. Mybatis介绍

    Mybatis一个持久层框架前身是由Apache管理的一个顶级项目ibatis,但是在2010后该项目交给Google code管理改名为Mybatis,并在2013迁移到Github

    Mybatis在ibatis的基础上做了一些封装优化。比如通过Mapper动态代理的方式开发Dao等

    Mybatis的特点是使用Xml文件来配置Sql语句。程序员自己写Sql语句,当需求变化时我们只需要修改配置文件即可,比较灵活

    另外,MybatisSql语句传参可以直接传入Java对象不必参数和占位符一一对应;把查询到结果映射为Java对象。 

    3.2. Hibernate架构回顾

     

    3.3. Mybatis架构

     

    n Mybatis配置

    全局配置文件SqlMapConfig.xml,配置了Mybatis的运行环境等信息。

    Mapper.xml文件即Sql映射文件,文件中配置了操作数据库的Sql语句。此文件需要在SqlMapConfig.xml中加载。

    通过Mybatis环境等配置信息构造SqlSessionFactory,即会话工厂。

    由会话工厂创建SqlSession即会话,操作数据库需要通过SqlSession进行。

    n Mybatis底层自定义了Executor执行器接口操作数据库Executor执行器调用具体的MappedStatement对象执行数据库操作动作

    MappedStatement也是Mybatis一个底层封装对象,它包装了Mybatis配置信息及Sql映射信息等Mapper.xml文件中一个Sql对应一个Mapped Statement对象Sqlid即是Mapped statementid

    n Executor通过MappedStatement在执Sql前将输入的java对象映射至Sql输入参数映射的意思就是Jdbc编程中PreparedStatement设置参数Executor通过MappedStatement在执行Sql后将输出结果映射至Java对象中,输出结果映射过程相当于Jdbc编程中对结果的解析处理过程

    3.4. 为什么要学习Mybatis

    越来越多的企业在用Mybatis,它的市场占有率越来越高。与之相比,Hibernate的市场占有率却在走低

    n Hibernate性能较差,操作数据库最终需要的是Sql,程序指令由框架内部层层翻译成很机械的Sql语句,程序人员无法干预,但是现在的系统往往对性能要求很高,Hibernate无法满足。Mybatis框架需要程序人员自己写Sql语句,优化方便。

    n Hibernate的学习门槛很高,精通和优化都需要很多的经验积累和很强的能力

    另:后续项目持久层使用Mybatis框架

    3.5. 下载Mybatis

    Mybaitsgithub.com管理

    下载地址:https://github.com/mybatis/mybatis-3/releases

    下载后的Mybatis如下:

    n mybatis-3.2.7.jar Mybatis的核心包

    n lib文件夹 Mybatis的依赖包

    n mybatis-3.2.7.pdf Mybatis官方使用手册

    4. Mybatis入门程序(Crud

    4.1. Mybatis QuickStart

    4.1.1. 目标

    快速构建并运行一个Mybatis工程,实现简单查询功能,通过快速演示先让学生对Mybatis框架的使用建立一个直观的认识。(细节知识在“Mybatis入门详解”部分讲解)

    4.1.2. Mybatis QuickStart功能需求

    基于已有数据表,快速构建Mybatis环境实现功能:根据id查询Blog表的一条记录

    4.1.3. 环境搭建

    4.1.3.1. 创建Maven工程

    效果如下:

    4.1.3.2. 引入坐标

    导入Mybatis包、Mysql数据库驱动包、Log4j包、junit测试包

    4.1.3.3. 加入配置文件

    resources目录下加入SqlMapConfig.xmllog4j.properties配置文件

     

    1SqlMapConfig.xml

    创建SqlMapConfig.xml,如下:

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE configuration

    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

    "http://mybatis.org/dtd/mybatis-3-config.dtd">

    <configuration>

    <environments default="development">

    <environment id="development">

    <transactionManager type="JDBC" />

    <dataSource type="POOLED">

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

    <property name="url"

    value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />

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

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

    </dataSource>

    </environment>

    </environments>

    <mappers>

    <mapper resource="sqlmap/BlogMapper.xml" />

    </mappers>

    </configuration>

    SqlMapConfig.xmlMybatis核心配置文件,配置文件内容为数据源、事务管理。

    2log4j.properties

    创建log4j.properties如下:

    # Global logging configuration

    log4j.rootLogger=DEBUG, stdout

    # Console output...

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

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

    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

    Mybatis默认使用log4j作为输出日志信息。

    4.1.4. 创建Pojo

    Pojo类在Mybatis进行Sql映射时使用,Pojo类通常与数据库表对应,

    数据库Blog表如下图:

     

    Blog.java如下:

    Public class Blog {

    private int id;

    private String author;// 作者

    private String title; // 博客标题

    get/set……

    4.1.5. Sql映射文件

    使用的Sql:

    SELECT * FROM BLOG WHERE ID = 1

    resources下的sqlmap子目录下创建Sql映射文件BlogMapper.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="test">

    <select id="queryBlogById" parameterType="Integer" resultType="com.itheima.mybatis.pojo.Blog">

      select * from blog where id=#{id}

      </select>

    </mapper>

    4.1.6. 加载映射文件

    Mybatis框架需要加载Mapper.xml映射文件

    BlogMapper.xml注册到SqlMapConfig.xml中,如下:

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE configuration

    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

    "http://mybatis.org/dtd/mybatis-3-config.dtd">

    <configuration>

    <environments default="development">

    <environment id="development">

    <transactionManager type="JDBC" />

    <dataSource type="POOLED">

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

    <property name="url"

    value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />

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

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

    </dataSource>

    </environment>

    <mappers>

    <mapper resource="sqlmap/BlogMapper.xml" />

    </mappers>

    </environments>

    </configuration>

    4.1.7. 测试程序

    测试程序步骤:

    1. 加载SqlMapConfig.xml配置文件

     2. 创建SqlSessionFactoryBuilder对象

    3. 创建SqlSessionFactory对象

     4. 创建SqlSession对象

     5. 执行SqlSession对象执行查询,获取结果User

     6. 打印结果

     7. 释放资源

    MybatisTest编写测试程序如下:

    public class MybatisTest {

    @Test

    public void testQueryBlogById() throws Exception {

    // 1. 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 2. 创建SqlSessionFactoryBuilder对象

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 3. 创建SqlSessionFactory对象

    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    // 4. 创建SqlSession对象

    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 5. 执行SqlSession对象执行查询,获取结果Blog

    // 第一个参数是BlogMapper.xml的statement的id,第二个参数是执行sql需要的参数;

    Blog blog = sqlSession.selectOne("queryBlogById", 1);

    // 6. 打印结果

    System.out.println(blog);

    // 7. 释放资源

    sqlSession.close();

    }

    }

    4.1.8. 效果

    测试结果如下图

     

    4.1.9. 小结

    从宏观上对开发Mybatis程序需要的组件有一个认识:

    1) SqlMapConfig.xml

    2) 存放SqlMapper映射文件

    3) Pojo

    4) 应用程序

    5) 关联SqlMapConfig.xmlMapper映射文件

    学习Mybatis成本低,只需重点关注Mapper映射文件即可

    4.2. Mybatis入门详解

    4.2.1. 功能需求

    创建一个用户表user,包含主键id、用户名、性别、生日及地址信息,使用MyBatis实现以下功能:

    根据用户id查询一个用户

    n 根据用户名称模糊查询用户列表

    n 添加一个用户

    根据用户id修改用户名

    根据用户id删除用户

    4.2.2. 创建用户表User

     

    测试数据如下:

    id

    username

    sex

    birthday

    address

    1

    张三

    1

    2018-5-13

    北京

    2

    李四

    1

    2018-5-14

    天津

    3

    王五

    1

    2018-5-15

    山东

    4

    王六

    1

    2018-5-16

    山西

    4.2.3. 实现根据用户id查询一个用户

    使用的Sql

    SELECT * FROM USER WHERE ID=1

    (1) POJO

    Public class User {

    private int id;

    private String username;// 用户名称

    private String sex; // 性别

    private Date birthday; // 生日

    private String address; // 地址

    get/set……

    (2) 映射文件

    resources目录下新建sqlmap子目录,创建UserMapper.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="test">

    <select id="queryUserById" parameterType="Integer" resultType="com.itheima.mybatis.pojo.User">

      select * from user where id=#{id}

      </select>

    </mapper>

    (3) 测试程序

    public class MybatisTest {

    @Test

    public void testQueryUserById() throws Exception { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    SqlSession sqlSession = sqlSessionFactory.openSession();

    User user = sqlSession.selectOne("queryUserById", 1);

    System.out.println(user);

    sqlSession.close();

    }

    }

    (4) 效果

     

    4.2.4. 实现根据用户名模糊查询用户列表

    使用的Sql

    SELECT * FROM USER WHERE USERNAME LIKE '%%'

    4.2.4.1. 方法一

    1映射文件

    UserMapper.xml配置文件中添加如下内容:

    <!-- 如果返回多个结果,mybatis会自动把返回的结果放在list容器中 -->

    <!-- resultType的配置和返回一个结果的配置一样 -->

    <select id="queryUserByUsername1" parameterType="string"

    resultType="com.itheima.mybatis.pojo.User">

    SELECT * FROM USER WHERE USERNAME LIKE #{username}

    </select>

    2测试程序

    MybatisTest中添加测试方法如下:

    @Test

    public void testQueryUserByUsername1() throws Exception {

    // 1. 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 2. 创建SqlSessionFactoryBuilder对象

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 3. 创建SqlSessionFactory对象

    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    // 4. 创建SqlSession对象

    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 5. 执行SqlSession对象执行查询,获取结果User

    // 查询多条数据使用selectList方法

    List<User> list = sqlSession.selectList("queryUserByUsername1", "%王%");

    // 6. 打印结果

    for (User user : list) {

    System.out.println(user);

    }

    // 7. 释放资源

    sqlSession.close();

    }

    3)效果

    测试效果如下图:

     

    4.2.4.2. 方法二

    1)映射文件

    UserMapper.xml配置文件中添加如下内容:

    <!-- 如果传入的参数是简单数据类型,${}里面必须写value -->

    <select id="queryUserByUsername2" parameterType="string"

    resultType="com.itheima.mybatis.pojo.User">

    SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'

    </select>

    2)测试程序

    MybatisTest中添加测试方法如下:

    @Test

    public void testQueryUserByUsername2() throws Exception {

    // 1. 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 2. 创建SqlSessionFactoryBuilder对象

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 3. 创建SqlSessionFactory对象

    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    // 4. 创建SqlSession对象

    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 5. 执行SqlSession对象执行查询,获取结果User

    // 查询多条数据使用selectList方法

    List<User> list = sqlSession.selectList("queryUserByUsername2", "王");

    // 6. 打印结果

    for (User user : list) {

    System.out.println(user);

    }

    // 7. 释放资源

    sqlSession.close();

    }

    3)效果

    测试结果如下图:

     

    4.2.5. 小结

    4.2.5.1. #{}${}

    关于#{}

    1#{}同于PreparedStatement中的占位符?,会自动传入的字符串数据加一对单引号,可以避免Sql注入

    比如  select * from user where username = #{username} ,传入的username为小,那么最后打印出来的就是

     select * from user where username = ‘小张’

    2#{}可以接收简单类型值或Pojo属性值 如果parameterType传输单个简单类型值,#{}括号中可以是任意名称。

    关于${}:

    1${}传入的数据直接显示生成在Sql,只是简单的拼接。如:order by ${id},如果传入的值是id,则解析成的Sqlorder by id

       如果上面的例子使用${},则成了select * from user where username = 小张

    2${}可以接收简单类型值或Pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是“value”这个字符串

    n 总结:

    1$方式一般用于传入数据库对象,例如传入表名order by 的字段

    2一般能用#的就别用$.

    4.2.5.2. parameterTyperesultType

    parameterType:指定输入参数类型

    resultType:指定输出结果类型,MybatisSql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List

    4.2.5.3. selectOneselectList

    selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:

    org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

    selectList可以查询一条或多条记录。

    4.2.6. 实现添加用户

    使用的Sql

    INSERT INTO USER (username,birthday,sex,address) VALUES

    ('黄忠','2016-07-26','1','三国')

    4.2.6.1. 映射文件

    UserMapper.xml配置文件中添加如下内容:

    <!-- 保存用户 -->

    <insert id="saveUser" parameterType="com.itheima.mybatis.pojo.User">

    INSERT INTO USER

    (username,birthday,sex,address) VALUES

    (#{username},#{birthday},#{sex},#{address})

    </insert>

    4.2.6.2. 测试程序

    MybatisTest中添加测试方法如下:

    @Test

    public void testSaveUser() throws Exception{

    // 1. 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 2. 创建SqlSessionFactoryBuilder对象

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 3. 创建SqlSessionFactory对象

    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    // 4. 创建SqlSession对象

    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 5. 执行SqlSession对象执行保存

    // 创建需要保存的User

    User user = new User();

    user.setUsername("张飞");

    user.setSex("1");

    user.setBirthday(new Date());

    user.setAddress("蜀国");

    sqlSession.insert("saveUser", user);

    System.out.println(user);

    // 需要进行事务提交

    sqlSession.commit();

    // 7. 释放资源

    sqlSession.close();

    }

    4.2.6.3. 效果

     

    如上所示,保存成功,但是id=0,需要解决id返回不正常的问题。

    4.2.6.4. Mysql自增主键返回

    查询Mysql自增idSql

    SELECT LAST_INSERT_ID()

    通过修改UserMapper.xml映射文件,可以将Mysql自增主键返回:

    如下添加selectKey 标签

    <!-- 保存用户 -->

    <insert id="saveUser" parameterType="com.itheima.mybatis.pojo.User">

    <!-- selectKey 标签实现主键返回 -->

    <!-- keyProperty:主键对应的pojo中的哪一个属性 -->

    <!-- order:设置在执行insert语句前执行查询id的sql,孩纸在执行insert语句之后执行查询id的sql -->

    <!-- resultType:设置返回的id的类型 -->

    <selectKey keyProperty="id" order="AFTER"

    resultType="Integer">

    SELECT LAST_INSERT_ID()

    </selectKey>

    INSERT INTO USER

    (username,birthday,sex,address) VALUES

    (#{username},#{birthday},#{sex},#{address})

    </insert>

    LAST_INSERT_ID():Mysql的函数,返回auto_increment自增列新记录id值。

    效果如下图所示:

     

    返回的id22,能够正确的返回id了。

    4.2.7. 修改用户

    根据用户id修改用户名

    使用的Sql

    UPDATE USER SET USERNAME = '赵云'  WHERE ID= 1

    4.2.7.1. 映射文件

    UserMapper.xml配置文件中添加如下内容:

    <!-- 更新用户 -->

    <update id="updateUserById" parameterType="com.itheima.mybatis.pojo.User">

    UPDATE USER SET

    USERNAME = #{username} WHERE ID = #{id}

    </update>

    4.2.7.2. 测试程序

    MybatisTest中添加测试方法如下:

    @Test

    public void testUpdateUserById() throws Exception{

    // 1. 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 2. 创建SqlSessionFactoryBuilder对象

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 3. 创建SqlSessionFactory对象

    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    // 4. 创建SqlSession对象

    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 5. 执行SqlSession对象执行更新

    // 创建需要更新的User

    User user = new User();

    user.setId(1);

    user.setUsername("关羽");

    sqlSession.update("updateUserById", user);

    // 需要进行事务提交

    sqlSession.commit();

    // 7. 释放资源

    sqlSession.close();

    }

    4.2.7.3. 效果

    测试效果如下图:

     

    4.2.8. 删除用户

    根据用户id删除用户

    使用的Sql
    DELETE FROM USER WHERE ID = 1

    4.2.8.1. 映射文件

    UserMapper.xml配置文件中添加如下内容:

    <!-- 删除用户 -->

    <delete id="deleteUserById" parameterType="Integer">

    delete from user where

    id=#{id}

    </delete>

    4.2.8.2. 测试程序

    MybatisTest中添加测试方法如下:

    @Test

    public void testDeleteUserById() throws Exception{

    // 1. 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 2. 创建SqlSessionFactoryBuilder对象

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 3. 创建SqlSessionFactory对象

    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    // 4. 创建SqlSession对象

    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 5. 执行SqlSession对象执行删除

    sqlSession.delete("deleteUserById", 1);

    // 需要进行事务提交

    sqlSession.commit();

    // 7. 释放资源

    sqlSession.close();

    }

    4.2.8.3. 效果

    测试效果如下图:

     

    4.3. Mybatis解决原生jdbc编程的问题

    1、 频繁创建、释放数据库连接造成系统资源浪费,影响系统性能。使用数据库连接池技术可以解决此问题。

    解决:SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库连接

    2、 Sql语句写在代码中造成代码不易维护,实际应用中Sql变化的可能较大,Sql变动需要改变java代码

    解决:Sql语句配置在XXXXmapper.xml文件中与Java代码分离

    3、 Sql语句传参数麻烦,因为Sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应(硬编码)。

    解决:Mybatis自动将Java对象映射至Sql语句,通过statement中的parameterType定义输入参数的类型

    4、 结果集解析麻烦(查询列硬编码),Sql变化会导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成Pojo对象解析比较方便。

    解决:Mybatis自动将Sql执行结果映射至Java对象,通过statement中的resultType定义输出结果的类型

    4.4. Maven中相关Jar包的安装

    电脑连接互联网时,直接使用Pom文件下载相关jar即可

    电脑未连接互联网时,可使用资料文件夹中提供的Maven仓库以覆盖的形式和你本机的Maven仓库进行合并

    1)提供的Maven仓库如下

     

    2)复制除.locks文件夹以外的所有内容,粘贴到你本地maven仓库的根目录下,如图所示

     

     

     

    5. Mybatis的两种Dao开发方式

    使用MyBatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper动态代理开发方法

    5.1. 功能需求

    使用MyBatis开发DAO实现以下的功能:

    根据用户id查询一个用户信息

    5.2. 原始Dao开发方式

    原始Dao开发方式需要程序员编写Dao接口和Dao实现类。

    5.2.1. 映射文件

    编写映射文件如下:(也可以使用入门程序完成的映射文件)

    <?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">

    <!-- namespace:命名空间用于隔离sql,映射mapper -->接口

    <mapper namespace="test">

    <!-- 根据id查询用户 -->

    <select id="queryUserById" parameterType="Integer"

    resultType="com.itheima.mybatis.pojo.User">

    select * from user where id = #{id}

    </select>

    </mapper>

    5.2.2. Dao接口

    先进行DAO的接口开发,编码如下:

    public interface UserDao {

    /**

     * 根据id查询用户

     *

     * @param id

     * @return

     */

    User queryUserById(int id);

    }

    5.2.3. Dao实现类

    编写的Dao实现类如下

    public class UserDaoImpl implements UserDao {

    private SqlSessionFactory sqlSessionFactory;

    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {

    super();

    this.sqlSessionFactory = sqlSessionFactory;

    }

    @Override

    public User queryUserById(int id) {

    // 创建SqlSession

    SqlSession sqlSession = this.sqlSessionFactory.openSession();

    // 执行查询逻辑

    User user = sqlSession.selectOne("queryUserById", id);

    // 释放资源

    sqlSession.close();

    return user;

    }

    }

    5.2.4. Dao测试

    创建一个JUnit的测试类,对UserDao进行测试,测试代码如下:

    public class UserDaoTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before

    public void init() throws Exception {

    // 创建SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 创建SqlsessionFactory

    this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    }

    @Test

    public void testQueryUserById() {

    // 创建DAO

    UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);

    // 执行查询

    User user = userDao.queryUserById(2);

    System.out.println(user);

    }

    }

    5.2.5. 思考

    原始方式开发Dao层时,如果接口中定义了很多方法,那么实现类中就得写很多的实现代码,但Dao层的逻辑总结起来就是增、删、改、查,是否可以不写实现类?

    5.3. Mapper动态代理方式

    5.3.1. 开发规范

    Mapper动态代理开发方式只需要程序员开发Mapper接口(相当于Dao接口),Mybatis框架会根据接口定义创建接口的动态代理对象,代理对象的方法同Dao接口实现类中的方法。

    Mapper接口开发需要遵循以下4个规范:

    n Mapper映射文件中的namespacemapper接口的类路径相同

    n Mapper接口方法名和Mapper映射文件中定义的每个Sqlid相同

    n Mapper接口方法的输入参数类型Mapper映射文件中定义的每个SqlParameterType的类型相同

    n Mapper接口方法的输出参数类型Mapper映射文件中定义的每个SqlresultType的类型相同

    5.3.2. Mapper.xml(映射文件)

    定义Mapper映射文件UserMapper.xml,放在resourcesmapper目录下,

    UserMapper.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">

    <!-- namespace:命名空间,用于隔离sql -->

    <!-- 还有一个很重要的作用,使用动态代理开发DAO,1. namespace必须和Mapper接口类路径一致 -->

    <mapper namespace="com.itheima.mybatis.mapper.UserMapper">

    <!-- 根据用户id查询用户 -->

    <!-- 2. id必须和Mapper接口方法名一致 -->

    <!-- 3. parameterType必须和接口方法参数类型一致 -->

    <!-- 4. resultType必须和接口方法返回值类型一致 -->

    <select id="queryUserById" parameterType="Integer"

    resultType="com.itheima.mybatis.pojo.User">

    select * from user where id = #{id}

    </select>

    </mapper>

    5.3.3. UserMapper(接口文件)

    创建UserMapper接口代码如下:

    public interface UserMapper {

    /**

     * 根据id查询

     *

     * @param id

     * @return

     */

    User queryUserById(int id);

    }

    5.3.4. 加载UserMapper.xml文件

    修改SqlMapConfig.xml文件,添加以下所示的内容:

    <!-- 加载映射文件 -->

    <mappers>

    <mapper resource="sqlmap/UserMapper.xml" />

    <mapper resource="mapper/UserMapper.xml" />

    </mappers>

    5.3.5. 测试

    编写的测试方法如下:

    public class UserMapperTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before

    public void init() throws Exception {

    // 创建SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    // 加载SqlMapConfig.xml配置文件

    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

    // 创建SqlsessionFactory

    this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    }

    @Test

    public void testQueryUserById() {

    // 获取sqlSession 

    SqlSession sqlSession = this.sqlSessionFactory.openSession();

    // 从sqlSession中获取Mapper接口的代理对象

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 执行查询方法

    User user = userMapper.queryUserById(2);

    System.out.println(user);

    sqlSession.close();

    }

    }

    5.3.6. 温馨提醒

    Mybatis官方推荐使用Mapper接口的方式开发Dao,这样程序员不用去开发实现类了。但是目前很多企业中还是用第一种方式开发Dao,因为在介绍Mybatis时,我们知道Mybatis的前身是ibatis,而ibatis没有提供这种方式开发Dao的,所有很多公司没有习惯使用第二种方式开发Dao。

    6. 全局配置文件SqlMapConfig.xml说明

    6.1. 配置内容和顺序

    SqlMapConfig.xml中配置的内容和顺序如下:

    properties(属性配置)

    settings(全局配置参数)

    typeAliases(类型别名)

    typeHandlers(类型处理器)

    objectFactory(对象工厂)

    plugins(插件)

    environments(环境集合属性对象)

    environment(环境子属性对象)

    transactionManager(事务管理)

    dataSource(数据源)

    mappers(映射器)

    注意:标签是有顺序的,如上。

    6.2. properties(属性)

    使用的properties的好处:配置数据共享

    db.properties配置文件内容如下:

    jdbc.driver=com.mysql.jdbc.Driver

    jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8

    jdbc.username=root

    jdbc.password=root

    SqlMapConfig.xml引用如下:

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE configuration

    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

    "http://mybatis.org/dtd/mybatis-3-config.dtd">

    <configuration>

    <!-- 是用resource属性加载外部配置文件 -->

    <properties resource="db.properties">

    <!-- 在properties内部用property定义属性 -->

    <!-- 如果外部配置文件有该属性,则内部定义属性被外部属性覆盖 -->

    <property name="jdbc.username" value="root123" />

    <property name="jdbc.password" value="root123" />

    </properties>

    <environments default="development">

    <environment id="development">

    <!-- 使用jdbc事务管理 -->

    <transactionManager type="JDBC" />

    <!-- 数据库连接池 -->

    <dataSource type="POOLED">

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

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

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

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

    </dataSource>

    </environment>

    </environments>

    <!-- 加载映射文件 -->

    <mappers>

    <mapper resource="sqlmap/UserMapper.xml" />

    <mapper resource="mapper/UserMapper.xml" />

    </mappers>

    </configuration>

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

    properties 元素体内定义的属性首先被读取。

    然后会读取properties 元素中resourceurl 加载的属性,它会覆盖已读取的同名属性。

    6.3. typeAliases(类型别名)

    6.3.1. Mybatis默认支持的别名

    别名

    映射的类型

    _byte

    byte

    _long

    long

    _short

    short

    _int

    int

    _integer

    int

    _double

    double

    _float

    float

    _boolean

    boolean

    string

    String

    byte

    Byte

    long

    Long

    short

    Short

    int

    Integer

    integer

    Integer

    double

    Double

    float

    Float

    boolean

    Boolean

    date

    Date

    decimal

    BigDecimal

    bigdecimal

    BigDecimal

    map

    Map

    6.3.2. 自定义别名

    SqlMapConfig.xml中配置如下:

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE configuration

    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

    "http://mybatis.org/dtd/mybatis-3-config.dtd">

    <configuration>

    <!-- 是用resource属性加载外部配置文件 -->

    <properties resource="db.properties">

    <!-- 在properties内部用property定义属性 -->

    <property name="jdbc.username" value="root123" />

    <property name="jdbc.password" value="root123" />

    </properties>

    <typeAliases>

    <!-- 单个别名定义 -->

    <typeAlias alias="user" type="com.itheima.mybatis.pojo.User" />

    <!-- 批量别名定义,扫描整个包下的类,别名为类名(大小写不敏感 -->

    <package name="com.itheima.mybatis.pojo" />

    <package name="其它包" />

    </typeAliases>

    <environments default="development">

    <environment id="development">

    <!-- 使用jdbc事务管理 -->

    <transactionManager type="JDBC" />

    <!-- 数据库连接池 -->

    <dataSource type="POOLED">

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

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

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

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

    </dataSource>

    </environment>

    </environments>

    <!-- 加载映射文件 -->

    <mappers>

    <mapper resource="sqlmap/UserMapper.xml" />

    <mapper resource="mapper/UserMapper.xml" />

    </mappers>

    </configuration>

    mapper.xml配置文件中,就可以使用设置的别名了

     

    注意:别名大小写不敏感,推荐使用<package/>批量定义别名

    6.4. mappers(映射器)

    Mapper配置的几种方法:

    6.4.1. 通过resource加载单个映射文件

    使用相对于类路径的资源(现在的使用方式)

    如:<mapper resource="sqlmap/UserMapper.xml" />

    6.4.2. 另外两种加载方式(仅支持Mapper动态代理开发Dao

    6.4.3. 通过mapper接口加载单个映射文件

    通过Mapper接口类加载单个映射文件

    使用mapper接口类路径,如:

    <mapper class="com.itheima.mybatis.mapper.UserMapper"/>

    注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

    批量加载映射文件

    加载指定包下的所有Mapper接口类,如:

    <package name="com.itheima.mybatis.mapper"/>

    注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

    注意:使用Mapper动态代理方式开发Dao层时,推荐使用<package/>批量加载的方式,这种方式也用的最多。

    7. MybatisHibernate区别

    1Hibernate是一个完全的ORM框架,Mybatis是一个不完全的ORM框架

    Hibernate自动化程度高,只需配置OR映射关系,不需要写Sql语句,怎么执行由框架底层控制。

    Mybatis虽然将SqlJava对象做了关系映射,但需要程序员自己写Sql。

    2Hibernate学习门槛高,Mybatis学习门槛较低

    Hibernate学习门槛高,精通门槛更高,设计O/R映射和Hibernate调优都需要很强的经验和能力

    Mybatis比较容易上手和掌握,重点关注Sql语句即可; 

    3Hibernate灵活度差但数据库无关性好,Mybatis灵活度高,但牺牲了数据库无关性

    Hibernate不能干预具体Sql的执行,但数据库无关性好,切换不同数据库时只需要切换数据库类型即可。

    Mybatis可严格控制Sql的执行性能,灵活度高,适合于软件的需求变化快而且多的软件,但灵活的前提是牺牲了数据库的无关性,如果要实现支持多种数据库的软件则需要自定义多套Sql映射文件,工作量大。

    选型原则

    总之,满足需求的前提下,只要做出维护性、扩展性好的软件架构都是好架构,框架只有合适的才是最好的。

    选型建议

    访问量小性能要求不高的内网项目,推荐使用全自动的Hibernate框架,可以提高开发效率。

    访问量大性能要求高的内网项目或者互联网项目,推荐使用Mybatis框架。

  • 相关阅读:
    spring-boot 参考链接
    Java中所涉及到的设计模式小记
    C# Xamarin开发 GenyMotion adb List of devices attached
    Java中的instanceof关键字
    Struts2文件下载
    Spring3基础原理解析
    JSP和Struts2、Hibernate、Spring3基础内容和原理
    Struts2多文件上传原理和示例
    Struts2单文件上传原理及示例
    Struts2国际化学习笔记
  • 原文地址:https://www.cnblogs.com/shan1393/p/9307229.html
Copyright © 2011-2022 走看看