Mybatis (two) Custom DAO and DAO && proxy configuration file meaning

Custom Process reanalysis

 

 Agent-based Dao implement CRUD operations

使用要求:
1、持久层接口和持久层接口的映射配置必须在相同的包下
2、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
3、SQL 语句的配置标签<select>,<insert>,<delete>,<update>的 id 属性必须和持久层接口的
方法名相同

According to ID inquiry

Add interface persistence layer findById Method

User findById(Integer userId);
<!-- 根据 id 查询 --> 
<select id="findById" resultType="com.itheima.domain.User" parameterType="int">
    select * from user where id = #{uid}
</select>
细节:
resultType 属性:
    用于指定结果集的类型。
parameterType 属性:
    用于指定传入参数的类型。
sql 语句中使用#{}字符: 它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。
具体的数据是由#{}里面的内容决定的。
#{}中内容的写法:
由于数据类型是基本类型,所以此处可以随意写。
public class MybatisTest {

    private InputStream in;
    private IUserDao userDao;

    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工厂对象,创建dao对象
        userDao = new UserDaoImpl(factory);
    }

    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        //6.释放资源
        in.close();
    }

    @Test
    public void testFindOne(){
        //5.执行查询一个方法
        User  user = userDao.findById(50);
        System.out.println(user);
    }
}

 

Save operation

The method of adding the new interface persistence layer

int saveUser(User user);
<!-- 保存用户--> 
<insert id="saveUser" parameterType="com.itheima.domain.User">
    insert into user(username,birthday,sex,address) 
values(#{username},#{birthday},#{sex},#{address})
</insert>
细节:
parameterType 属性:
    代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
sql 语句中使用#{}字符: 它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。
具体的数据是由#{}里面的内容决定的。
#{}中内容的写法:
    由于我们保存方法的参数是 一个 User 对象,此处要写 User 对象中的属性名称。
    它用的是 ognl 表达式。
        ognl 表达式:
            它是 apache 提供的一种表达式语言,全称是:
            Object Graphic Navigation Language 对象图导航语言
            它是按照一定的语法格式来获取数据的。
            语法格式就是使用 #{对象.对象}的方式
            #{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,
并调用getUsername()方法把值取出来。
但是我们在 parameterType 属性上指定了实体类名称,
所以可以省略 user.  
而直接写 username。
@Test
public void testSave(){
    User user = new User();
    user.setUsername("modify User property");
    user.setAddress("北京市顺义区");
    user.setSex("男");
    user.setBirthday(new Date());
    System.out.println("保存操作之前:"+user);
    //5.执行保存方法
    userDao.saveUser(user);
    System.out.println("保存操作之后:"+user);
}
打开 Mysql 数据库发现并没有添加任何记录,原因是什么?
这一点和 jdbc 是一样的,我们在实现增删改时一定要去控制事务的提交,那么在 mybatis 中如何控制事务
提交呢?
可以使用:session.commit();来实现事务提交。加入事务提交后的代码如下:
@After//在测试方法执行完成之后执行
public void destroy() throws Exception{
    session.commit();
    //7.释放资源
    session.close();
    in.close();
}

 Extended problem: the new user id 's return value

新增用户后,同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相
当于我们要在新增后将自动增长 auto_increment 的值返回。
<insert id="saveUser" parameterType="USER">
    <!-- 配置保存时获取插入的 id --> 
    <selectKey keyColumn="id" keyProperty="id" resultType="int">
        select last_insert_id();
    </selectKey>
    insert into user(username,birthday,sex,address) 
                values(#{username},#{birthday},#{sex},#{address})
</insert>

Users update

The method of adding the updated interface persistence layer

int updateUser(User user);
<!-- 更新用户 --> 
<update id="updateUser" parameterType="com.itheima.domain.User">
    update user set username=#{username},birthday=#{birthday},sex=#{sex},
    address=#{address} where id=#{id}
</update>
 @Test
 public void testUpdate(){
        User user = new User();
        user.setId(50);
        user.setUsername("userdaoimpl update user");
        user.setAddress("北京市顺义区");
        user.setSex("女");
        user.setBirthday(new Date());

        //5.执行保存方法
        userDao.updateUser(user);
    }

 

User deletes

Add Remove method in the persistence layer interface

int deleteUser(Integer userId);
<!-- 删除用户 --> 
<delete id="deleteUser" parameterType="java.lang.Integer">
    delete from user where id = #{uid}
</delete>
@Test
public void testDeleteUser() throws Exception {
    //6.执行操作
    int res = userDao.deleteUser(52);
    System.out.println(res);
}

 

Users fuzzy query

In the persistence layer interface add fuzzy query method

List<User> findByName(String username);
<!-- 根据名称模糊查询 --> 
<select id="findByName" resultType="com.itheima.domain.User" parameterType="String">
 select * from user where username like #{username}
</select>
@Test
 public void testFindByName(){
    //5.执行查询一个方法
     List<User> users = userDao.findByName("%王%");
     for(User user : users){
         System.out.println(user);
     }
 }
在控制台输出的执行 SQL 语句如下:
我们在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标
识%。配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”。

 

 

Another configuration of fuzzy query 

第一步:修改 SQL 语句的配置,配置如下:
<!-- 根据名称模糊查询 --> 
<select id="findByName" parameterType="string" resultType="com.itheima.domain.User">
     select * from user where username like '%${value}%'
</select>
我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写
法就是固定的,不能写成其它名字。
第二步:测试,如下:
/**
* 测试模糊查询操作
 */
@Test
public void testFindByName(){
 //5.执行查询一个方法
    List<User> users = userDao.findByName("王");
    for(User user : users){
        System.out.println(user);
    } 
}

在控制台输出的执行 SQL 语句如下:
可以发现,我们在程序代码中就不需要加入模糊查询的匹配符%了,这两种方式的实现效果是一样的,但执行
的语句是不一样的

# {} And $ {} distinction 

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

Fuzzy query $ {value} source code analysis 

我们一起来看 TextSqlNode 类的源码:
这就说明了源码中指定了读取的 key 的名字就是”value”,所以我们在绑定参数时就只能叫 value 的名字
了

Query using aggregate functions

Add in the persistence layer interface polymerization method Query

int findTotal();
<!-- 查询总记录条数 --> 
<select id="findTotal" resultType="int">
    select count(*) from user;
</select>
@Test
public void testFindTotal() throws Exception {
    //6.执行操作
    int res = userDao.findTotal();
    System.out.println(res);
}

 

Mybatis and JDBC relatively programming

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 定义输出结果的
类型。

Mybatis parameters depth

parameterType configuration parameters

Instructions for use

 SQL 语句传参,使用标签的 parameterType 属性来设定。该属性的取值可以
是基本类型,引用类型(例如:String 类型),还可以是实体类类型(POJO 类)。
同时也可以使用实体类的包装类,本章节将介绍如何使用实体类的包装类作为参数传递。

Precautions

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

In the description of mybatis official documents, which are supported by the default alias. You can refer TypeAliasRegistery.class source.

 

Transfer pojo wrapper object 

开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查
询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo 类中包含 pojo。
需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。

Write QueryVo

public class QueryVo {

    private User user;

    public User getUser() {
        return user;
    }

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

Write the persistence layer interface

List<User> findUserByVo(QueryVo vo);

Persistence layer interface mapping file

<!-- 根据用户名称模糊查询,参数变成一个 QueryVo 对象了 --> 
<select id="findByVo" resultType="com.itheima.domain.User"
     parameterType="com.itheima.domain.QueryVo">
    select * from user where username like #{user.username};
</select>
@Test
public void testFindByQueryVo() {
    QueryVo vo = new QueryVo();
    User user = new User();
    user.setUserName("%王%");
    vo.setUser(user);
    List<User> users = userDao.findByVo(vo);
    for(User u : users) {
        System.out.println(u);
    } 
}

Mybatis output result of the package

resultType 配置结果类型

resultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。
我们在前面的 CRUD 案例中已经对此属性进行过应用了。
需要注意的是,它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须
使用全限定类名。例如:我们的实体类此时必须是全限定类名
同时,当是实体类名称是,还有一个要求,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法
实现封装。

基本类型示例

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

实体类类型示例

List<User> findAll();
<!-- 配置查询所有操作 --> 
<select id="findAll" resultType="com.itheima.domain.User">
    select * from user
</select>

特殊情况示例

修改实体类

public class User implements Serializable {
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
public Integer getUserId() {
return userId; }
public void setUserId(Integer userId) {
this.userId = userId; }
public String getUserName() {
return userName; }
public void setUserName(String userName) {
this.userName = userName; }
public Date getUserBirthday() {
return userBirthday; }
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday; }
public String getUserSex() {
return userSex; }
public void setUserSex(String userSex) {
this.userSex = userSex; }
public String getUserAddress() {
return userAddress; }
public void setUserAddress(String userAddress) {
this.userAddress = userAddress; }
@Override
public String toString() {
return "User [userId=" + userId + ", userName=" + userName + ", userBirthday="
+ userBirthday + ", userSex="
+ userSex + ", userAddress=" + userAddress + "]"; 
} 
}
List<User> findAll();
<!-- 配置查询所有操作 --> 
<select id="findAll" resultType="com.itheima.domain.User">
    select * from user
</select>
@Test
public void testFindAll() {
    List<User> users = userDao.findAll();
    for(User user : users) {
        System.out.println(user);
    } 
}

为什么名称会有值呢?
因为: mysql windows 系统中不区分大小写!
 
 
 
 
修改映射配置
使用别名查询
<!-- 配置查询所有操作 --> 
<select id="findAll" resultType="com.itheima.domain.User">
    select id as userId,username as userName,birthday as userBirthday,
    sex as userSex,address as userAddress from user
</select>
如果我们的查询很多,都使用别名的话写起来很麻烦
 

resultMap 结果类型

resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类
型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询

定义 resultMap

<!-- 建立 User 实体和数据库表的对应关系
    type 属性:指定实体类的全限定类名
    id 属性:给定一个唯一标识,是给查询 select 标签引用用的。
    --> 
<resultMap type="com.itheima.domain.User" id="userMap"> 
    <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 标签:用于指定主键字段
result 标签:用于指定非主键字段
column 属性:用于指定数据库列名
property 属性:用于指定实体类属性名称

映射配置

<!-- 配置查询所有操作 --> 
<select id="findAll" resultMap="userMap">
    select * from user
</select>

测试结果

@Test
public void testFindAll() {
    List<User> users = userDao.findAll();
    for(User user : users) {
        System.out.println(user);
    } 
}
运行结果:

Mybatis 传统 DAO 层开发 

使用 Mybatis 开发 Dao,通常有两个方法,即原始 Dao 开发方式和 Mapper 接口代理开发方式。而现在主流
的开发方式是接口代理开发方式,这种方式总体上更加简便。

Mybatis 实现 DAO 的传统开发方式

持久层 Dao 接口

public interface IUserDao {

    /**
     * 查询所有用户
     * @return
     */
    List<User> findAll();

    /**
     * 保存用户
     * @param user
     */
    void saveUser(User user);

    /**
     * 更新用户
     * @param user
     */
    void updateUser(User user);

    /**
     * 根据Id删除用户
     * @param userId
     */
    void deleteUser(Integer userId);

    /**
     * 根据id查询用户信息
     * @param userId
     * @return
     */
    User findById(Integer userId);

    /**
     * 根据名称模糊查询用户信息
     * @param username
     * @return
     */
    List<User> findByName(String username);

    /**
     * 查询总用户数
     * @return
     */
    int findTotal();

}

持久层 Dao 实现类

public class UserDaoImpl implements IUserDao {

    private SqlSessionFactory factory;

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

    @Override
    public List<User> findAll() {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法,实现查询列表
        List<User> users = session.selectList("com.itheima.dao.IUserDao.findAll");//参数就是能获取配置信息的key
        //3.释放资源
        session.close();
        return users;
    }

    @Override
    public void saveUser(User user) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现保存
        session.insert("com.itheima.dao.IUserDao.saveUser",user);
        //3.提交事务
        session.commit();
        //4.释放资源
        session.close();
    }

    @Override
    public void updateUser(User user) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现更新
        session.update("com.itheima.dao.IUserDao.updateUser",user);
        //3.提交事务
        session.commit();
        //4.释放资源
        session.close();
    }

    @Override
    public void deleteUser(Integer userId) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现更新
        session.update("com.itheima.dao.IUserDao.deleteUser",userId);
        //3.提交事务
        session.commit();
        //4.释放资源
        session.close();
    }

    @Override
    public User findById(Integer userId) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法,实现查询一个
        User user = session.selectOne("com.itheima.dao.IUserDao.findById",userId);
        //3.释放资源
        session.close();
        return user;
    }

    @Override
    public List<User> findByName(String username) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法,实现查询列表
        List<User> users = session.selectList("com.itheima.dao.IUserDao.findByName",username);
        //3.释放资源
        session.close();
        return users;
    }

    @Override
    public int findTotal() {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法,实现查询一个
        Integer count = session.selectOne("com.itheima.dao.IUserDao.findTotal");
        //3.释放资源
        session.close();
        return count;
    }
}

持久层映射配置

<?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.itheima.dao.IUserDao">

    <!-- 查询所有 -->
    <select id="findAll" resultType="com.itheima.domain.User">
        select * from user;
    </select>

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

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

    <!-- 删除用户-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{uid}
    </delete>
    
    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="com.itheima.domain.User">
        select * from user where id = #{uid}
    </select>

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

    <!-- 获取用户的总记录条数 -->
    <select id="findTotal" resultType="int">
        select count(id) from user;
    </select>
</mapper>
public class MybatisTest {

    private InputStream in;
    private IUserDao userDao;

    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工厂对象,创建dao对象
        userDao = new UserDaoImpl(factory);
    }

    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        //6.释放资源
        in.close();
    }

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll(){
        //5.执行查询所有方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }

    }
    /**
     * 测试保存操作
     */
    @Test
    public void testSave(){
        User user = new User();
        user.setUsername("dao impl user");
        user.setAddress("北京市顺义区");
        user.setSex("男");
        user.setBirthday(new Date());
        System.out.println("保存操作之前:"+user);
        //5.执行保存方法
        userDao.saveUser(user);

        System.out.println("保存操作之后:"+user);
    }

    /**
     * 测试更新操作
     */
    @Test
    public void testUpdate(){
        User user = new User();
        user.setId(50);
        user.setUsername("userdaoimpl update user");
        user.setAddress("北京市顺义区");
        user.setSex("女");
        user.setBirthday(new Date());

        //5.执行保存方法
        userDao.updateUser(user);
    }

    /**
     * 测试删除操作
     */
    @Test
    public void testDelete(){
        //5.执行删除方法
        userDao.deleteUser(54);
    }

    /**
     * 测试删除操作
     */
    @Test
    public void testFindOne(){
        //5.执行查询一个方法
        User  user = userDao.findById(50);
        System.out.println(user);
    }

    /**
     * 测试模糊查询操作
     */
    @Test
    public void testFindByName(){
        //5.执行查询一个方法
        List<User> users = userDao.findByName("%王%");
        for(User user : users){
            System.out.println(user);
        }
    }

    /**
     * 测试查询总记录条数
     */
    @Test
    public void testFindTotal(){
        //5.执行查询一个方法
        int count = userDao.findTotal();
        System.out.println(count);
    }



}

SqlMapConfig.xml配置文件

配置内容

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

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

properties(属性)

在使用 properties 标签配置时,我们可以采用两种方式指定属性配置。

第一种

<properties> 
    <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
    <property name="jdbc.url" value="jdbc:mysql://localhost:3306/eesy"/>
    <property name="jdbc.username" value="root"/>
    <property name="jdbc.password" value="1234"/>
</properties>

第二种

classpath 下定义 db.properties 文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=1234
properties 标签配置
<!-- 配置连接数据库的信息
    resource 属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下
    resource="jdbcConfig.properties"
    url 属性:
        URL: Uniform Resource Locator 统一资源定位符
            http://localhost:8080/mystroe/CategoryServlet URL
            协议 主机 端口 URI
        URI:Uniform Resource Identifier 统一资源标识符
            /mystroe/CategoryServlet
            它是可以在 web 应用中唯一定位一个资源的路径
--> 
<properties url=
file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.properties">
</properties>
此时我们的 dataSource 标签就变成了引用上面的配置
<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>

typeAliases(类型别名)

自定义别名:

在 SqlMapConfig.xml 中配置:
<typeAliases>
<!-- 单个别名定义 --> 
<typeAlias alias="user" type="com.itheima.domain.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --> 
    <package name="com.itheima.domain"/>
    <package name="其它包"/>
</typeAliases>

mappers(映射器)

<mapper resource=" " />

使用相对于类路径的资源
如:<mapper resource="com/itheima/dao/IUserDao.xml" />

<mapper class=" " />

使用 mapper 接口类路径
如:<mapper class="com.itheima.dao.UserDao"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。

<package name=""/>

注册指定包下的所有 mapper 接口
如:<package name="cn.itcast.mybatis.mapper"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。

Mybatis 流程


代理dao的执行流程

自己编写dao的执行流程 

发布了85 篇原创文章 · 获赞 5 · 访问量 1万+

Guess you like

Origin blog.csdn.net/qq_40837106/article/details/103870708