MyBatis 02

2,MyBatis映射文件解析

MyBatis最强大的地方就在于它的语句映射,正由于它的强大,映射对应的xml文件代码编写就会相应简单。可以明显感知到比同功能的jdbc代码少了很多很多。MyBatis致力于减少使用成本,让用户更专注于SQL代码。

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • cache:该命名空间的缓存配置。
  • cache-ref:引用其它命名空间的缓存配置。
  • resultMap:描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
  • sql:可被其它语句引用的可重用语句块。
  • insert:映射插入语句。
  • update:映射更新语句。
  • delete:映射删除语句。
  • select:映射查询语句。

2.1,先准备表

create database if not exists mydb;
use mydb;
CREATE TABLE tb_depart(
    id int PRIMARY KEY AUTO_INCREMENT,
    name varchar(20)
);
CREATE TABLE tb_employee(
   id int PRIMARY KEY AUTO_INCREMENT,
   name varchar(20),
   age int,
   did int
);
INSERT INTO tb_depart(name) VALUES('武装部');
INSERT INTO tb_employee(name, age, did) VALUES('赵子龙', 30, 1);
INSERT INTO tb_employee(name, age, did) VALUES('关羽', 35, 1);

在这里插入图片描述
在这里插入图片描述

2.2,insert

这个元素用于执行insert语句向数据库中插入数据

2.2.1,添加方法

在EmployeeMapper接口中添加插入方法

public interface EmployeeMapper {
    // 插入
    void add(Employee employee);
}

2.2.2,编写映射

在EmployeeMapper.xml文件中实现add方法

<?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.xianopeng.mapper.EmployeeMapper">
    <!-- 插入 -->
    <insert id="add" parameterType="Employee">
    	<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
        	select last_insert_id()
    	</selectKey>
        insert into tb_employee(name,age,did) values (#{name}, #{age}, #{did})
    </insert>
</mapper>

2.2.3,测试

@Test
    public void testAdd() {
        SqlSession session = MyBatisUtil.openSession();
        try {
            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            Employee employee = new Employee().setName("张飞").setAge(20).setDid(1);
            mapper.add(employee);
            session.commit();
            System.out.println("employee = " + employee);
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }
    }

2.3,select

这个元素用于查询数据的顶级元素,主属性如下:

  • id:它是一个唯一标识,与接口中的方法名称一致。
  • parameterType:将会传入这条语句的参数的类全限定名或别名,这个属性是可选的。
  • resultType:返回的结果是集合时是定义集合中元素的类型。它可以使用全限定名,也可以使用别名。它不能和 resultMap 同时使用。
  • resultMap:对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。

2.3.1,添加查询方法

在EmployrrMapper接口中添加查询方法

// 查询
    List<Employee> getEmployeeByName(String name);

2.3.2,实现

在EmployeeMapper.xm文件中写对应的实现

<select id="getEmployeeByName" resultType="Employee">
    select id,name,age,did from tb_employee where name like #{name}
</select>

2.3.3,测试

@Test
public void testGetEmployeeByName() {
    SqlSession session = MyBatisUtil.openSession();
    EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    String name = "刘";
    String s = "%" + name + "%";
    List<Employee> employees = mapper.getEmployeeByName(s);
    employees.forEach(System.out::println);
}

2.4,带参数查询

在 MyBatis 中,查询语句是可以带参数,当参数是一个的时候很简单,当参是多个的时候,我们可以把它封装到实体对象中,也可以用逗号的方式来分隔。

2.4.1,添加方法

// 多参数查询
List<Employee> getEmployeeByNameAndAge(String name, int age);

2.4.2,实现

<!-- 多参数查询 -->
<select id="getEmployeeByNameAndAge" resultType="Employee">
    select id,name,age,did from tb_employee where name=#{param1} and age=#{param2}
</select>

2.4.3测试

// 多参数查询
@Test
public void testGetEmployeeByNameAndAge() {
    SqlSession session = MyBatisUtil.openSession();
    EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    List<Employee> employees = mapper.getEmployeeByNameAndAge("刘备", 20);
    employees.forEach(System.out::println);
}

2.5,#{}和${}

在执行sql语句时,我们使用#{}来给参数传值
例如:

<select id="getEmployeeByAnnotation" resultType="Employee">
    select id,name,age,did from tb_employee where name=#{name} and age=#{age}
</select>

最终在mybatis中会执行的sql语句则为:

select id,name,age,did from tb_employee where name=? and age=?

这种方式是使用的 PreparedStatement 对象来处理的。
还有一种方法是使用${}传值,它会将给定值拼接到sql语句中:
例如:

<select id="getEmployeeByAnnotation" resultType="Employee">
    select id,name,age,did from tb_employee where name=${name} and age=${age}
</select>

在mybatis中执行的sql语句为:

select id,name,age,did from tb_employee where name=刘备 and age=20

实际上它使用的就是 Statement 对象来处理 SQL,所以我们在开发中,不要使用 ${} ,而是使用 #{} 来赋值。

2.6,将查询结果封装到map中

2.6.1,添加方法

Map<String, Object> getEmployeeById(int id);

2.6.2,实现

<select id="getEmployeeById" resultType="map">
    select id,name,age,did from tb_employee where id=#{id}
</select>

2.6.3,测试

@Test
public void testGetEmployeeById() {
    SqlSession session = MyBatisUtil.openSession();
    EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    Map<String, Object> result = mapper.getEmployeeById(5);
    System.out.println(result);
}

2.6.4,查询多条时的修改

将结果封装到Employee对象中,将Map集合改为Map<Integer,Employee>

@MapKey("id")
Map<Integer, Employee> getEmployees();

实现:

<select id="getEmployees" resultType="Employee">
    select id,name,age,did from tb_employee
</select>

测试:

@Test
public void testGetEmployees() {
    SqlSession session = MyBatisUtil.openSession();
    EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    Map<Integer, Employee> result = mapper.getEmployees();
    System.out.println(result);
}

2.7,resultMap

resultMap元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

2.7.1,添加方法

Employee findEmployeeById(int id);

2.7.2,实现

<resultMap id="rm" type="Employee">
    <id property="id" column="id" />
    <result property="name" column="name"/>
    <result property="age" column="age"/>
    <result property="did" column="did"/>
</resultMap>
<select id="findEmployeeById" resultMap="rm">
    select id,name,age,did from tb_employee where id=#{id}
</select>

在 select 标签上使用 resultMap 属性来指定返回的结果集,它的值必须与某个 resultMap 标签定义的 id 属性的值一致。
resultMap 标签说明:

  • id:用于给这个配置取一个唯一的名称,便于使用时引用。
  • type:定义这就结果集的返回类型,可以是别名,也可以是全限定名。

resultMap子标签介绍:

  • id:用来定义主键关联
    • property:实体类中哪个属性作为主键
    • column:表中哪个字段作为主键
  • result:用于定义除了主键外的字段关联
    • property:实体类中的属性名
    • column:表中的字段

2.7.3,测试

@Test
public void testFindEmployeeById() {
    SqlSession session = MyBatisUtil.openSession();
    EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    Employee employee = mapper.findEmployeeById(5);
    System.out.println(employee);
}

2.8,association

2.8.1,在员工类中添加对部门的关联

@Data
@Accessors(chain = true)
public class Employee {
    private Integer id;
    private String name;
    private int age;
    private Integer did;
    // 关联部门,它是多对一关系
    private Department depart;
}

2.8.2,在部门类接口添加方法

根据部门编号查询部门名称

    // 根据ID查询部门
    Department getDepartmentById(int id);

实现:

<mapper namespace="com.xianopeng.mapper.DepartmentMapper">
    <!-- 根据ID查询部门 -->
    <select id="getDepartmentById" resultType="Department">
        select id,name from tb_depart where id=#{id};
    </select>
</mapper>

2.8.3,添加员工方法

Employee getById(int id);

实现:

<resultMap id="rm1" type="Employee">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="age" property="age"/>
    <result column="did" property="depart.id"/>
    <result column="dname" property="depart.name"/>
</resultMap>
<select id="getById" resultMap="rm1">
    select e.id id, e.name name, age, d.name dname
    from tb_employee e, tb_depart d
    where e.did=d.id and e.id=#{id}
</select>

2.8.4,使用association配置联合查询:

<resultMap id="rm1" type="Employee">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="age" property="age"/>
    <association property="depart" javaType="Department">
        <id property="id" column="did"/>
        <result property="name" column="dname"/>
    </association>
</resultMap>
<select id="getById" resultMap="rm1">
    select e.id id, e.name name, age, d.id did, d.name dname
    from tb_employee e, tb_depart d
    where e.did=d.id and e.id=#{id}
</select>

association 标签来实现联合查询,属性说明如下:

  • property:用于指定返回类型对象(Employee)中那个属性来作为联合查询
  • javaType:用于定义被关联的属性对应的 Java 类型

2.9,collection

关联查询,查询部门时候,将部门下的员工也查询出来

2.9.1,修改部门实体类

@Data
@Accessors(chain = true)
public class Department {
    private Integer id;
    private String name;
    // 一对多
    private Set<Employee> emps;
}

2.9.2,实现

<resultMap id="depMap" type="Department">
    <id property="id" column="did" />
    <result property="name" column="dname"/>
    <collection property="emps" ofType="Employee">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
    </collection>
</resultMap>
<select id="getById" resultMap="depMap">
    select d.id did,d.name dname, e.id id,e.name name,age
    from tb_depart d left join tb_employee e on d.id = e.did
    where d.id=#{id};
</select>

2.9.3,测试

@Test
public void testGetByDid() {
    SqlSession session = MyBatisUtil.openSession();
    DepartmentMapper mapper = session.getMapper(DepartmentMapper.class);
    Department department = mapper.getById(1);
    System.out.println(department.getName());
    department.getEmps().forEach(System.out::println);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值