MyBatis框架的基本使用

学习回顾:MyBatis框架的入门学习

1、基于代理Dao实现单表CRUD操作

  在对 MyBatis 的单表 CRUD 操作之前,我们先对之前的测试案例中一些重复的操作抽取出来,进行简单的分解整合,简化代码的书写。

public class MybatisTest {
    public static void main(String[] args) throws Exception {
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建 SqlSessionFactory 的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.使用构建者创建工厂对象 SqlSessionFactory
        SqlSessionFactory factory = builder.build(in);
        //4.使用 SqlSessionFactory 生产 SqlSession 对象
        SqlSession session = factory.openSession();
        //5.使用 SqlSession 创建 dao 接口的代理对象
        UserDao userDao = session.getMapper(UserDao.class);
        //6.使用代理对象执行查询所有方法
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
        //7.释放资源
        session.close();
        in.close();
    }
}

  分解整合后:

public class MybatisTest {
    private InputStream inputStream;
    private SqlSessionFactory factory;
    private SqlSession session;
    private UserDao userDao;

    @Before //在测试方法执行之前执行
    public void Init() throws Exception {
        // 1.读取配置文件
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2.创建 SqlSessionFactory 的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3.使用构建者创建工厂对象 SqlSessionFactory
        factory = builder.build(inputStream);
        // 4.使用 SqlSessionFactory 生产 SqlSession 对象
        session = factory.openSession();
        // 5.使用 SqlSession 创建 dao 接口的代理对象
        userDao = session.getMapper(UserDao.class);
    }

    @After //在测试方法执行完成之后执行
    public void Destroy() throws Exception {
        // 7.释放资源
        session.close();
        inputStream.close();
    }

    @Test
    public void testFindAll(){
        // 6.使用代理对象执行查询所有方法
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }
}

1.1、查询操作:select

  (1)在Dao持久层接口中添加查询方法

    /**
     * 根据用户的ID查询
     */
    User findById(Integer userId);

  (2)在映射配置文件中配置sql语句

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="id" resultType="com.atlantis.domain.User">
        select * from user where id = #{uid}
    </select>
描述
resultType 属性用于指定结果集的类型。
parameterType 属性用于指定传入参数的类型。
sql 语句中使用 #{} 字符代表占位符,用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。
#{} 中内容的写法因为数据类型是int基本类型,则此处可以随意写。

  (3)在测试类中编写方法测试

    @Test
    public void testFindById() {
        // 6.使用代理对象执行查询所有方法
        User user = userDao.findById(4);
        System.out.println(user);
    }

在这里插入图片描述

1.2、查询操作扩展案例:模糊查询

  (1)在Dao持久层接口中添加模糊查询方法

    /**
     * 根据名称模糊查询
     */
    List<User> findUserByName(String username);

  (2)在映射配置文件中配置sql语句

    <!-- 根据名称模糊查询 -->
    <select id="findUserByName" parameterType="String" resultType="com.atlantis.domain.User" >
        select * from user where username like #{username}
    </select>

  (3)在测试类中编写方法测试

    @Test
    public void testFindUserByName() {
        // 6.使用代理对象执行查询所有方法
        List<User> users = userDao.findUserByName("%test%");
        for (User user : users) {
            System.out.println(user);
        }
    }

在这里插入图片描述
  观察下图控制台输出的SQL语句,因为我们在配置文件中没有加入%%来作为模糊查询的条件,所以在传入字符串实参时,急需要给定模糊查询的标识%%,即userDao.findUserByName("%test%");。而配置文件中的#{username}也只是个占位符,所以 SQL 语句显示为?
在这里插入图片描述
  当然,模糊查询还有另一种配置方式。
  ①修改 SQL 语句的配置,将原来的#{}占位符,改成了${value}。需要我们注意的是,如果使用这种模糊查询写法,那么${value}的写法就是固定的,不能写成其它名字。

    <!-- 根据名称模糊查询 -->
    <select id="findUserByName" parameterType="String" resultType="com.atlantis.domain.User" >
        select * from user where username like '%${value}%'
    </select>

  ②在测试类中,我们就不需要给定模糊查询的标识%%,直接给定查询条件即可。

    @Test
    public void testFindUserByName() {
        // 6.使用代理对象执行查询所有方法
        List<User> users = userDao.findUserByName("test");
        for (User user : users) {
            System.out.println(user);
        }
    }

  观察下图控制台输出的SQL语句,可以发现这两种方式的实现效果是一样的,但执行的语句却是不一样的。使用这种方式来模糊查询话,就不需要加入模糊查询的匹配符%%了。
在这里插入图片描述

#{}${} 的区别:
  #{} 表示一个占位符号:通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{}括号中可以是 value 或其它名称。
  ${} 表示拼接 sql 串:通过${}可以将 parameterType 传入的内容拼接在 sql中且不进行 jdbc 类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。

1.3、查询操作扩展案例:查询使用聚合函数

  (1)在Dao持久层接口中添加查询方法

    /**
     * 查询用户的总记录条数
     */
    int findUserTotal();

  (2)在映射配置文件中配置sql语句

    <!-- 查询用户的总记录条数 -->
    <select id="findUserTotal" resultType="int">
        select count(*) from user
    </select>

  (3)在测试类中编写方法测试

    @Test
    public void testFindUserTotal() {
        // 6.使用代理对象执行查询所有方法
        int total = userDao.findUserTotal();
        System.out.println(total);
    }

在这里插入图片描述

1.4、保存操作:insert

  (1)在Dao持久层接口中添加保存方法

    /**
     * 保存用户
     */
    int saveUser(User user);

  (2)在映射配置文件中配置sql语句

    <!-- 保存用户 -->
    <select id="saveUser" parameterType="com.atlantis.domain.User">
        insert into user(username,sex,birthday,address) value(#{username},#{sex},#{birthday},#{address})
    </select>
描述
parameterType 属性用于指定传入参数的类型。传入的是一个类的对象,所以类型就写类的全名称。
sql 语句中使用 #{} 字符代表占位符,用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。
#{} 中内容的写法因为 parameterType 属性是一个User对象,则此处要写User对象的属性名称,使用的是 OGNL 表达式。

  OGNL 是 apache 提供的一种表达式语言,全称为Object Graphic Navigation Language,对象图导航语言。
  按照一定的语法格式#{对象.对象}来获取数据的,例如#{user.username},它会先去找user对象,然后在user对象中找到username属性,并调用getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user.而直接写 #{username}

  (3)在测试类中编写方法测试

    @Test
    public void testSaveUser() {
        // 6.使用代理对象执行查询所有方法
        User user = new User();
        user.setUsername("testName");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("深圳");
        userDao.saveUser(user);
    }

在这里插入图片描述
  打开 Mysql 数据库发现并没有添加任何记录,原因是什么?
  因为 Mybatis 和 JDBC 是一样的,在实现增删改操作时一定要控制事务的提交,name在 Mybatis 中如何控制事务的提交呢?
  可以使用session.commit();来实现事务提交。加入事务提交后的代码如下:

    @After //在测试方法执行完成之后执行
    public void Destroy() throws Exception {
        // 提交事务
        session.commit();
        // 7.释放资源
        session.close();
        inputStream.close();
    }

  在数据库中我们可以发现,因为 id 是自增的,那么id=8去哪了呢?原因是在上面的案例中,我们进行了保存操作,但是因为没有进行 commit 提交事务,所以这条数据插入数据库后(这时候 id 已经自增为8了),就立刻被回滚(Rolling Back)了,回滚后的id=8就不会再分配给下一条记录了。
  在这里插入图片描述

1.5、保存操作扩展案例:获取插入数据的id值

  在实际开发过程中,我们在保存一个用户之后也想要得到这个新增用户的 id。比较笨的解决方案就是新增用户之后,再去查询此用户的 id,可以发现比较麻烦且浪费数据库资源。
  其实数据库中就有一条语句select last_insert_id()是用来获取插入数据的id,那么如何在Mybatis的映射配置文件中使用这条语句?请看下面代码:

    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="com.atlantis.domain.User">
        <!-- 配置插入操作后,获取插入数据的id -->
        <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username,sex,birthday,address) value(#{username},#{sex},#{birthday},#{address})
    </insert>
描述
keyColumn="id"数据库表的 id 列
keyProperty="id"实体类User中的 id 属性
resultType="int"指定返回的数据类型
order选择在什么时候执行这条语句。AFTER(之后执行),BEFORE(之前执行)

在这里插入图片描述

1.6、更新操作:update

  (1)在Dao持久层接口中添加更新方法

    /**
     * 更新用户
     */
    int updateUser(User user);

  (2)在映射配置文件中配置sql语句

    <!-- 更新用户 -->
    <update id="updateUser" parameterType="com.atlantis.domain.User">
        update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}
    </update>

  (3)在测试类中编写方法测试

    @Test
    public void testUpdateUser() {
        // 6.使用代理对象执行查询所有方法
        // 根据id查询用户
        User user = userDao.findById(4);
        user.setAddress("更新后的地址信息");
        // 更新用户信息
        userDao.updateUser(user);
    }

在这里插入图片描述

1.7、删除操作:delete

  (1)在Dao持久层接口中添加删除方法

    /**
     * 删除用户
     */
    int deleteUser(Integer userId);

  (2)在映射配置文件中配置sql语句

    <!-- 删除用户 -->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id=#{uid}
    </delete>

  (3)在测试类中编写方法测试

    @Test
    public void testDeleteUser() {
        // 6.使用代理对象执行查询所有方法
        int flag = userDao.deleteUser(12);
        System.out.println(flag);
    }

在这里插入图片描述

2、MyBatis与JDBC编程的比较

(1)数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
  解决:在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。

(2)Sql 语句写在代码中造成代码不易维护,实际应用 Sql 变化的可能较大,Sql 变动需要改变 Java 代码。
  解决:将 Sql 语句放在 xxxMapper.xml(或xxxDao.xml)映射配置文件中与 Java 代码分离。

(3)向sql语句传参数麻烦,因为Sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数对应。
  解决:Mybatis 自动将 Java 对象映射至 Sql 语句,通过 statement 中的 parameterType 定义输入参数的类型。

(4)对结果集解析麻烦,Sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。
  解决:Mybatis 自动将 Sql 执行结果映射至 Java 对象,通过 statement 中的 resultType 定义输出结果的类型。

3、MyBatis的参数深入

3.1、ParameterType参数设置

  在上面的学习中已经介绍了 SQL 语句传参,使用标签的 ParameterType 属性来设定。该属性的取值可以是基本类型,引用类型(例如 String 类型),还可以是实体类型( POJO 类),同时也可以使用实体类的包装类。

  在这里需要我们注意的是,基本类型和 String 我们可以直接写类型名称,也可以使用包名.类名的方式,例如:java.lang.String
  而实体类类型,目前只能使用全路径类名。原因是 Mybatis 在加载时就已经把常用的数据类型注册了别名,从而使我们在使用时可以不写包名。而我们的实体类并没有注册别名,所以必须写全路径类名。

  在 Mybatis 的官方文档中的说明:
在这里插入图片描述
  在第六章【MyBatis的SqlMapConfig.xml配置详解】中,讲解了如何去注册实体类的别名。

3.2、传递pojo包装对象

  开发中通过 pojo 传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其他的查询条件,这是就可以使用包装对象传递输入参数。
  (1)编写pojo包装对象实体类

import java.io.Serializable;

public class QueryVo implements Serializable {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

  (2)在Dao持久层接口中添加方法

    /**
     * 根据QueryVo中的条件查询
     */
    List<User> findUserByVo(QueryVo vo);

  (3)在映射配置文件中配置sql语句

    <!-- 根据用户名称模糊查询,参数变成一个QueryVo对象 -->
    <select id="findUserByVo" resultType="com.atlantis.domain.User" parameterType="com.atlantis.domain.QueryVo">
        select * from user where username like #{user.username}
    </select>

  (4)在测试类中编写方法测试

    @Test
    public void testFindUserByQueryVo() {
        // 6.使用代理对象执行查询所有方法
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%test%");
        vo.setUser(user);
        List<User> users = userDao.findUserByVo(vo);
        for (User u : users) {
            System.out.println(u);
        }
    }

在这里插入图片描述

4、MyBatis的输出结果封装

4.1、ResultType配置结果类型

  ResultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。在前面的第一章【基于代理Dao实现单表CRUD操作】中的案例中已经对此属性进行过应用了。
  需要注意的是,它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全路径类名。例如:自己定义的实体类此时必须是全路径类名。
  (1)基本类型示例
在这里插入图片描述
  (2)实体类类型示例
在这里插入图片描述
  需要注意的是,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。真的是这样子的吗?下面给出示例:
  首先修改实体类,注意此时的实体类属性和数据库表的列名不一致了:

public class User {
    private Integer userId;
    private String userName;
    private String userSex;
    private Date userBirthday;
    private String userAddress;

	// 省略get、set和toString方法。
}

  查询测试结果:

    @Test
    public void testFindAll() {
        // 6.使用代理对象执行查询所有方法
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }

在这里插入图片描述
  可以发现,因为实体类属性和数据库表的列名不一致,导致无法实现对查询结果的封装。那么,为什么 userName 有值呢?原因是 Mysql 在 windows 系统中不区分大小写的,因此这个属性与数据库表的列名一致,所以能够进行封装。
  那么怎么解决实体类属性和数据库表的列名不一致的问题呢?比较的笨的方法就是在 SQL 语句中使用别名,这样实体类中的属性名称就和查询语句中的列名(查询结果后的列,非数据库表的列)保持一致了。

    <!-- 查询所有用户 -->
    <select id="findAll" resultType="com.atlantis.domain.User">
        select id as userId,username as userName,sex as userSex,birthday as userBirthday,address as userAddress from user
    </select>

在这里插入图片描述
  使用这种方案话,如果查询较多的情况下,都在 SQL 语句使用别名话不仅麻烦,而且影响代码阅读。因此引申出了 ResultMap 类型,下面讲解 ResultMap 的使用。

4.2、ResultMap类型

  ResultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系,从而实现封装。同时 ResultMap 可以实现将查询结果映射为复杂类型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
  (1)定义 ResultMap
  建立 User 实体类和数据库表的对应关系。

    <resultMap id="userMap" type="com.atlantis.domain.User">
        <id column="id" property="userId" />
        <result column="username" property="userName" />
        <result column="sex" property="userSex" />
        <result column="address" property="userAddress" />
        <result column="birthday" property="userBirthday" />
    </resultMap>
描述
id="userMap"属性给定一个唯一标识,是给查询 Select 标签引用的
type="com.atlantis.domain.User"属性指定实体类的全路径类名
<id />标签用于指定主键字段
<result />标签用于指定非主键字段
column="username"属性用于指定数据库表的列名
property="userName"用于指定实体类属性的名称

  (2)映射配置

    <!-- 查询所有用户 -->
    <select id="findAll" resultMap="userMap">
        select * from user
    </select>

  (3)测试类及运行结果

    @Test
    public void testFindAll() {
        // 6.使用代理对象执行查询所有方法
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }

在这里插入图片描述

5、MyBatis传统Dao层开发(了解)

  使用 Mybatis 开发 Dao层,通常有两个方法,即原始 Dao 开发方式和 Mapper 接口代理开发方式。而现在主流的开发方式是接口代理开发方式,这种方式总体上更加简便。上面的案例也主要以接口代理开发方式为主。
  现在给大家介绍一下基于传统编写 Dao 实现类的开发方式。
  (1)实体类

public class User {
    private Integer userId;
    private String userName;
    private String userSex;
    private Date userBirthday;
    private String userAddress;

	// 省略get、set和toString方法

  (2)Dao持久层接口

public interface UserDao {
    /**
     * 查询所有用户
     */
    List<User> findAll();

    /**
     * 查询用户的总记录条数
     */
    int findUserTotal();

    /**
     * 根据用户的ID查询
     */
    User findById(Integer userId);

    /**
     * 保存用户
     */
    int saveUser(User user);

    /**
     * 更新用户
     */
    int updateUser(User user);

    /**
     * 删除用户
     */
    int deleteUser(Integer userId);
}

  (3)Dao持久层实现类

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory factory;

    public UserDaoImpl(SqlSessionFactory factory) {
        this.factory = factory;
    }

    public List<User> findAll() {
        SqlSession session = factory.openSession();
        List<User> users = session.selectList("com.atlantis.dao.UserDao.findAll");
        session.close();
        return users;
    }

    public int findUserTotal() {
        SqlSession session = factory.openSession();
        int flag = session.selectOne("com.atlantis.dao.UserDao.findUserTotal");
        session.close();
        return flag;
    }

    public User findById(Integer userId) {
        SqlSession session = factory.openSession();
        User user = session.selectOne("com.atlantis.dao.IUserDao.findById", userId);
        session.close();
        return user;
    }

    public int saveUser(User user) {
        SqlSession session = factory.openSession();
        int flag = session.insert("com.atlantis.dao.IUserDao.saveUser", user);
        session.commit();
        session.close();
        return flag;
    }

    public int updateUser(User user) {
        SqlSession session = factory.openSession();
        int flag = session.update("com.atlantis.dao.IUserDao.updateUser", user);
        session.commit();
        session.close();
        return flag;
    }

    public int deleteUser(Integer userId) {
        SqlSession session = factory.openSession();
        int flag = session.delete("com.atlantis.dao.IUserDao.deleteUser", userId);
        session.commit();
        session.close();
        return flag;
    }
}

  (4)持久层映射配置文件

<?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="com.atlantis.dao.UserDao">
    <resultMap id="userMap" type="com.atlantis.domain.User">
        <id column="id" property="userId" />
        <result column="username" property="userName" />
        <result column="sex" property="userSex" />
        <result column="address" property="userAddress" />
        <result column="birthday" property="userBirthday" />
    </resultMap>

    <!-- 查询所有用户 -->
    <select id="findAll" resultMap="userMap">
        select * from user
    </select>

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="int" resultType="com.atlantis.domain.User">
        select * from user where id = #{uid}
    </select>

    <!-- 查询用户的总记录条数 -->
    <select id="findUserTotal" resultType="int">
        select count(*) from user
    </select>

    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="com.atlantis.domain.User">
        <!-- 配置插入操作后,获取插入数据的id -->
        <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username,sex,birthday,address) value(#{userName},#{userSex},#{userBirthday},#{userAddress})
    </insert>

    <!-- 更新用户 -->
    <update id="updateUser" parameterType="com.atlantis.domain.User">
        update user set username=#{userName},sex=#{userSex},birthday=#{userBirthday},address=#{userAddress} where id=#{userId}
    </update>

    <!-- 删除用户 -->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id=#{uid}
    </delete>

  (5)测试类

public class MybatisCRUDTest {
    private InputStream inputStream;
    private SqlSessionFactory factory;
    private UserDao userDao;

    @Before //在测试方法执行之前执行
    public void Init() throws Exception {
        // 1.读取配置文件
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2.创建 SqlSessionFactory 的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3.使用构建者创建工厂对象 SqlSessionFactory
        factory = builder.build(inputStream);
        // 4.创建Dao接口的实现类
        userDao = new UserDaoImpl(factory);
    }

    @After //在测试方法执行完成之后执行
    public void Destroy() throws Exception {
        // 6.释放资源
        inputStream.close();
    }

    @Test
    public void testFindAll() {
        // 5.执行操作
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }

    @Test
    public void testFindUserTotal() {
        // 5.执行操作
        int total = userDao.findUserTotal();
        System.out.println(total);
    }

    @Test
    public void testFindById() {
        // 5.执行操作
        User user = userDao.findById(4);
        System.out.println(user);
    }

    @Test
    public void testSaveUser() {
        // 5.执行操作
        User user = new User();
        user.setUserName("testName");
        user.setUserSex("男");
        user.setUserBirthday(new Date());
        user.setUserAddress("深圳");
        System.out.println("保存之前:" + user);
        userDao.saveUser(user);
        System.out.println("保存之后:" + user);
    }

    @Test
    public void testUpdateUser() {
        // 5.执行操作
        // 根据id查询用户
        User user = userDao.findById(4);
        user.setUserAddress("更新后的地址信息");
        // 更新用户信息
        userDao.updateUser(user);
    }

    @Test
    public void testDeleteUser() {
        // 5.执行操作
        int flag = userDao.deleteUser(12);
        System.out.println(flag);
    }
}

6、MyBatis的SqlMapConfig.xml配置详解

6.1、SqlMapConfig.xml的配置内容

  在这里插入图片描述

6.2、Properties(属性)

  在使用 properties 标签配置时,可以采用两种方式指定属性配置。
  (1)第一种:通过properties元素的子元素来传递

<?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">
<!-- Mybatis的主配置文件 -->
<configuration>
    <properties>
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </properties>
    
    <!-- 环境集合属性 -->
    <environments default="mysql">
        <!-- Mysql的配置环境 -->
        <environment id="mysql">
            <!-- 配置事务的类型 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 指定映射配置文件的位置,即每个Dao接口独立的配置文件 -->
    <mappers>
        <mapper resource="com/atlantis/dao/UserDao.xml"/>
    </mappers>
</configuration>

  (1)第二种:通过指定properties配置文件来传递
  首先在 classpath 下定义 db.properties 文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8
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">
<!-- Mybatis的主配置文件 -->
<configuration>
	<!-- 引用db.properties配置文件 -->
    <properties resource="db.properties" />
    
    <!-- 环境集合属性 -->
    <environments default="mysql">
        <!-- Mysql的配置环境 -->
        <environment id="mysql">
            <!-- 配置事务的类型 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <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>

    <!-- 指定映射配置文件的位置,即每个Dao接口独立的配置文件 -->
    <mappers>
        <mapper resource="com/atlantis/dao/UserDao.xml"/>
    </mappers>
</configuration>

6.3、TypeAliases (类型别名)

  在前面提到了 Mybatis 支持的默认别名外,我们也可以采用自定义别名的方式来开发代码。
  在 SqlMapConfig.xml 配置文件中配置:

    <typeAliases>
        <!-- 单个实体类别名 -->
        <typeAlias type="com.atlantis.domain.User" alias="User" />
        <!-- 批量定义别名,扫描整个包下的类,别名为类名(首字母大小写均可) -->
        <package name="com.atlantis.domain"/>
    </typeAliases>

  若报元素类型为 "configuration" 的内容必须匹配 "(properties?,settings?,typeAliases?,typeHandlers?, objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"错误,说明配置文件的节点顺序错误。在该案例中,请把typeAliases节点放置在properties节点后,environments节点前。

  设置完别名后,在映射配置文件中指定类型时就可以不使用全路径类名了。
在这里插入图片描述

6.4、Mappers (映射器)

    <!-- 指定映射配置文件的位置,即每个Dao接口独立的配置文件 -->
    <mappers>
        <!-- 使用相对于类路径的资源 -->
        <mapper resource="com/atlantis/dao/UserDao.xml"/>
        <!-- 使用Mapper接口类路径 -->
        <mapper class="com.atlantis.dao.UserDao" />
        <!-- 注册指定包下所有的Mapper接口 -->
        <!-- 使用此种方法要求Mapper接口名称和Mapper映射文件名要相同,且放在同一个目录中 -->
        <package name="com.atlantis.dao"/>
    </mappers>

  
  后面讲解一些 Mybatis 的进阶使用:https://blog.csdn.net/q961250375/article/details/102766120

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值