MyBatis学习笔记

MyBatis

Mybatis简介

什么是Mybatis

是一个持久层框架,功能是简化之前我们学习的处理数据库连接的JDBC代码

早期叫Ibatis

我们称的SSM实际上就是Spring+SpringMvc+Mybatis的组合

SSI实际上就是SSM

配置Mybatis

步骤1:导入ssm的依赖

<!-- SpringMVC -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
<!-- Spring JDBC依赖,必须与其它Spring依赖使用完全相同的版本 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
<!-- Mybatis框架 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.0</version>
</dependency>
<!-- MyBatis整合Spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.1</version>
</dependency>
<!-- Thymeleaf -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.11.RELEASE</version>
</dependency>
<!-- Thymeleaf整合Spring -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.0.11.RELEASE</version>
</dependency>
<!-- 连接MySQL数据库的依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.15</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.21</version>
</dependency>
<!-- 单元测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

步骤2:

复制jdbc.properties文件到resources文件夹下

db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/vrd?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
db.username=root
db.password=root
db.maxActive=10
db.initialSize=2

步骤3:

编写Mybatis的配置文件

@PropertySource("classpath:jdbc.properties")
public class MyBatisConfig {

    @Bean
    public DataSource dataSource(
            @Value("${db.driver}") String driver,
            @Value("${db.url}") String url,
            @Value("${db.username}") String username,
            @Value("${db.password}") String password,
            @Value("${db.maxActive}") int maxActive,
            @Value("${db.initialSize}") int initialSize) {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        ds.setMaxActive(maxActive);
        ds.setInitialSize(initialSize);
        return ds;
    }
}

配置完成测试配置可用

在test中创建测试类

 @Test
    public void testDataSource() throws SQLException {
        DataSource ds=ctx.getBean(
                "dataSource",DataSource.class);
        String sql="select username from vrduser where id=1";
        try (Connection conn=ds.getConnection()){
            Statement st=conn.createStatement();
            ResultSet rs=st.executeQuery(sql);
            while(rs.next()){
                System.out.println(rs.getString(1));
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

MyBatis基本使用

我们下面完成一个HelloWorld程序

步骤1:

新建一个cn.tedu.mapper包

包中新建一个接口DemoMapper

public interface DemoMapper {

    //下面的方法就是Mybatis实现的查询方法了
    //不需要编写实现类
    @Select("select username from vrduser where id=1")
    public String hello();

}

上面的接口会由我们注入的SqlSessionFactory来自动生成实现类

注入这个类

MyBatisConfig中代码如下

@PropertySource("classpath:jdbc.properties")
@MapperScan("cn.tedu.mapper")
public class MyBatisConfig {

    @Bean
    public DataSource dataSource(
      //代码略
    }

    //SqlSessionFactory这个类时Mybatis中的一个重要的类
    //它的功能非常强大,能根据接口中声明的信息
    //自动实现这个接口的实现类,并将这个实现类注入到Spring容器以便我们使用
    @Bean
    public SqlSessionFactory sqlSessionFactory(
            DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean=
                new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }
}

需要注意类上新加了注解@MapperScan(“cn.tedu.mapper”)

表示指定功能强大的SqlSessionFactory类要扫描并生成实现类的包

配置完毕

执行测试

 @Test
    public void testFactory(){
        SqlSessionFactory factory=ctx.getBean(
                "sqlSessionFactory",SqlSessionFactory.class);
        System.out.println(factory);
    }
    //执行Mapper接口中的方法
    @Test
    public void testUsername(){
        DemoMapper mapper=ctx.getBean(
                "demoMapper",DemoMapper.class);
        String name=mapper.hello();
        System.out.println(name);
    }

使用Mybatis实现简单CRUD操作

准备数据

我们新建一个数据库,添加一些数据以备Mybatis使用

create database tedu_ums;
use tedu_ums

创建表

CREATE TABLE t_user (
  id INT(11) AUTO_INCREMENT COMMENT '用户id',
  username VARCHAR(20) UNIQUE NOT NULL COMMENT '用户名',
  password VARCHAR(20) NOT NULL COMMENT '密码',
  age INT COMMENT '年龄',
  phone VARCHAR(20) COMMENT '手机号码',
  email VARCHAR(20) COMMENT '电子邮箱',
  PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;

添加数据

INSERT INTO t_user (username, password, phone, age, email) VALUES 
  ('Frank01', '1234', '13800138001', 28, 'frank01@163.com'),
  ('Frank04', '1234', '13800138004', 33, 'frank04@163.com'),
  ('Frank05', '1234', '13800138005', 21, 'frank05@163.com'),
  ('Frank09', '1234', '13800138009', 26, 'frank09@163.com'),
  ('Frank06', '1234', '13800138006', 29, 'frank06@163.com'),
  ('Frank11', '1234', '13800138011', 24, 'frank11@163.com'),
  ('Frank12', '1234', '13800138012', 23, 'frank12@163.com'),
  ('Frank07', '1234', '13800138007', 31, 'frank07@163.com'),
  ('Frank08', '1234', '13800138008', 22, 'frank08@163.com'),
  ('Frank02', '1234', '13800138002', 27, 'frank02@163.com'),
  ('Frank03', '1234', '13800138003', 32, 'frank03@163.com'),
  ('Frank10', '1234', '13800138010', 30, 'frank10@163.com'),
  ('Frank13', '1234', '13800138013', 25, 'frank13@163.com');

需要注意我们更换的数据库

需要在jdbc.properties配置文件中修改

db.url=jdbc:mysql://localhost:3306/tedu_ums?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true

将数据库名修改为tedu_ums

查询功能

下面无论做什么操作,都需要对应t_user表的实体类

否则不方便,所以我们先创建它

新建一个包,标准的实体类包名称有很多,都是业界常见的

entity\bean\model\pojo\domain等

我们创建cn.tedu.entity

public class User implements Serializable {

    //注意:所有属性名必须和数据库的列名完全一致
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String phone;
    private String email;

    public User(){
    }

    public User(Integer id, String username, String password, Integer age, String phone, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.phone = phone;
        this.email = email;
    }
    ..省略其它代码
}

执行按id查询出User对象的查询方法

mapper包中新建一个接口UserMapper

其中编写方法,代码如下:

public interface UserMapper {

    @Select("select id,username,password,age,phone,email from t_user where id=#{id}")
    User findUserById(Integer id);
}

测试:

@Test
    public void selectId(){
        UserMapper mapper=ctx.getBean(
                "userMapper", UserMapper.class);
        User user=mapper.findUserById(1);
        System.out.println(user);

    }

运行输出一个用户的id即可

Mybatis从数据库中查询出指定id的数据后

会根据列名和java实体类的属性对应的关系一一赋值

依赖的是实体类的set方法

上面是查询一行

下面我们来查询多行

UserMapper接口添加如下方法

 @Select("select id,username,password,age,phone,email" +
            " from t_user")
    List<User> findAllUsers();

测试代码

@Test
    public void selectAll(){
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        List<User> list=mapper.findAllUsers();
        for (User u:list) {
            System.out.println(u);
        }
    }

新增功能

在UserMapper中添加如下方法

//新增用户的方法
    //返回的Integer是受影响的行数 新增1行时 1行受影响表示成功
    @Insert("insert into t_user values" +
            "(null,#{username},#{password},#{age},#{phone},#{email})")
    Integer insertUser(User user);

sql语句中出现的#{xxx}实际上是去调用user对象的getXxx方法

所以#{}中的内容必须和user属性对应

测试

@Test
    public void insert(){
        User user=new User(null,"Tom","123",
                28,"13811012345","tom@tedu.cn");
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        Integer num=mapper.insertUser(user);
        System.out.println(num);

    }

今后做项目时可能需要这样的需求

新增一个对象到数据库后,我们想立即获得这个对象的id怎么实现

下面我们就来学习

如果新增User后立即获得这个User的id

UserMapper新增方法

 //下面的方法是新增用户并将新增后自增的id赋值给用户对象的属性
    @Insert("insert into t_user values" +
            "(null,#{username},#{password},#{age},#{phone},#{email})")
    //useGeneratedKeys表示获取生成的主键 true就是要获取
    //keyProperty表示获得的主键要赋给user的哪个属性
    @Options(useGeneratedKeys = true, keyProperty = "id")
    Integer insertUserWithId(User user);

测试代码

 @Test
    public void insertWithId(){
        User user=new User(null,"Jerry","456",
                21,"13811013789","jerry@tedu.cn");
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        Integer num=mapper.insertUserWithId(user);
        System.out.println(num);
        System.out.println(user);

    }

修改功能

我们先实现一个全行修改

根据user对象的id将id匹配的行除了id列之外的所有列都修改为当前user对象的值

在UserMapper中新建方法

@Update("update t_user set username=#{username}," +
            "password=#{password},age=#{age},phone=#{phone}," +
            "email=#{email} where id=#{id}")
    Integer updateUser(User user);

测试

 @Test
    public void updateUser(){
        User user=new User(16,"LiLei","888",25,
                "13812345678","lilei@qq.com");
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        Integer num=mapper.updateUser(user);
        System.out.println(num);
    }

下面我们实现一个按照给定的id修改email的方法

在Mapper中编写代码如下

//按id修改email的方法
    @Update("update t_user set email=#{email} where id=#{id}")
    Integer updateEmailById(Integer id,String email);

Mybatis框架接口中编写的方法如果有两个或以上的参数会出现问题
因为默认情况下.java文件编译成.class文件后
所有局部变量的名称都会丢失所以在运行时Mybatis不能根据给定的参数名称
去对应sql语句中#{}中的内容

所以上面编写的方法在测试时会报错

解决这个问题有3个方案

1.将#{}里面的内容修改为arg0\arg1

 @Update("update t_user set email=#{arg1} where id=#{arg0}")
    Integer updateEmailById(Integer id,String email);

其中#{arg0}表示参数列表中的第一个参数

#{arg1}表示第二个参数

2.将#{}里面的内容修改为param1\param2

 @Update("update t_user set email=#{param2} where id=#{param1}")
    Integer updateEmailById(Integer id,String email);

其中#{param1}表示参数列表中的第一个参数

#{param2}表示第二个参数

3.使用Mybatis提供的注解标记每个参数对应的名称

  @Update("update t_user set email=#{email} where id=#{id}")
    Integer updateEmailById(
            @Param("id") Integer id,
            @Param("email") String email);

其中@Param(“id”)表示这个注解后面的参数对应#{id}

其中@Param(“email”)表示这个注解后面的参数对应#{email}

测试代码

 @Test
    public void updateEmail(){
        Integer id=14;
        String email="tom@sina.com";
        UserMapper userMapper=ctx.getBean(
                "userMapper",UserMapper.class);
        Integer num=userMapper.updateEmailById(id,email);
        System.out.println(num);
    }

删除功能

删除功能是这几个功能中最简单的

UserMapper中编写方法代码如下

//按id删除用户
    @Delete("delete from t_user where id=#{id}")
    public Integer deleteById(Integer id);

测试代码

@Test
    public void deleteById(){
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        Integer num=mapper.deleteById(14);
        System.out.println(num);
    }

MyBatis复杂映射

上次课程中实现的Sql语句都是比较简单的

简单sql语句可以直接使用注解编写在接口中的方法上

但是如果sql语句比较复杂,注解的方式功能就比较有限了

需要使用Xml文件来支持功能更强大的查询

使用Xml文件来映射sql语句

步骤1:

实现Xml映射的sql语句也是在接口中编写一个方法

但是这个方法不需要加注解

public interface UserMapper {

    //xml映射sql语句的方法
    //不需要在方法上写注解
    String getUsernameById();

	///......
}

步骤2:

在resources文件夹下新建一个mappers的文件夹

其中新建一个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 属性执行映射到 UserMapper接口 -->
<mapper namespace="cn.tedu.mapper.UserMapper">

    <!-- 需要将返回值类型声明给SqlSessionFactory -->
    <!-- 使用resultType指定类型,类型需要使用全类名表示  -->
    <select id="getUsernameById" resultType="java.lang.String">
        select username from t_user where id=1
    </select>
</mapper>

步骤3:

将我们配置xml文件的路径记录在jdbc.properties文件中,以便配置类使用

db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/tedu_ums?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
db.username=root
db.password=root
db.maxActive=10
db.initialSize=2
#新增的配置!!!!!!!!
mybatis.mapper.location=classpath:mappers/*.xml

步骤4:

在MybatisConfig类中修改对SqlSessionFactory类的注入

 @Bean
    public SqlSessionFactory sqlSessionFactory(
            DataSource dataSource,
            //使用@Value指定xml文件的位置,并赋值给Resource数组
            @Value("${mybatis.mapper.location}")
            Resource[] mapperLocations
            ) throws Exception {
        SqlSessionFactoryBean bean=
                new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(mapperLocations);
        return bean.getObject();
    }

步骤5:

测试

 @Test
    public void testHelloXml(){
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        String username=mapper.getUsernameById();
        System.out.println(username);
    }

方法的可变参数

可变参数方法的定义

 //可变参数方法的定义
    //在参数列表中参数类型后加...表示这个参数是可变参数
    //1.一个方法只能有一个可变参数,而且必须是这个方法的最后一个参数
    //2.在方法内部处理这个参数时,将这个参数视为一个数组
    public static void  sum(int... nums){
        //假设这个方法的业务是计算所有参数之和
        int sum=0;
        for(int i=0;i<nums.length;i++){
            sum+=nums[i];
        }
        System.out.println(sum);
    }

可变参数方法的调用

 public static void main(String[] args) {
        //可变参数方法调用事项
        //1.可变参数的数量可以是0个,1个或多个
        //2.可变参数的位置可以传入该类型的数组
        sum();
        sum(100);
        sum(8,10,20);
        int[] a={5,9,1,2,4,2,3,7};
        sum(a);
    }

使用Xml处理动态Sql语句

动态foreach

如果现在要一次性根据id删除多条记录

怎么操作?

如果使用按id删除一条记录的方法来遍历删除,由于连库次数多,删除效率一定低

我们可以使用动态sql语句的foreach来动态生成SQL语句删除记录

实现一条sql语句删除多行:

delete from t_user where id in (?,?,?)

直接使用可变参数指定要删除的id

UserMapper方法定义如下

//动态foreach删除
    Integer deleteById(Integer... ids);

xml文件中代码如下

<!-- 动态foreach删除  -->
    <delete id="deleteById">
        delete from t_user where id in (
            <!-- array就是数组类型参数,当参数中只有唯一数组类型时,自动赋值 -->
            <!-- item表示从数组\集合中获取出的元素 -->
            <!-- separator是多个元素之间的分隔符-->
            <foreach collection="array" item="id" separator=",">
                #{id}
            </foreach>
        )
    </delete>

<foreach>标签还有两个属性

分别是open和close

表示循环开始之前和结束之后加什么内容

显示运行\生成的sql语句

我们希望能够看到我们自己编写的sql运行的状态

所以我们可以利用log4j日志记录的功能将Mybatis运行的过程输出到控制台

步骤1:

首先保证有log4j的依赖

<dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.25</version>
</dependency>

步骤2:在resources文件夹在新增log4j.properties配置文件

log4j.rootLogger=ERROR, stdout

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 Mapper
log4j.logger.cn.tedu.mapper=TRACE

动态分支结构

在Mybatis的Xml文件中除了可以进行循环

还可以进行分支结构

即当满足指定条件时添加指定sql语句

实现方式有if标签和choose标签

<if test="表达式">
   sql语句片段
</if>

Mybaits中没有支持if标签的else标签只能手动编写条件表达式的反表达式

如果非要类似else标签的支持,可以选用choose标签

<choose>
	<when test="表达式">
		当条件满足时生成的sql语句片段
	</when>
	<!--  允许编写多个when标签  -->
	<otherwise>
		当所有when表达式都没有满足时生成的sql片段
	</otherwise>
</choose>

下面我们来实现几个具体的业务

回忆一下我们上次课讲的全行修改

UPDATE t_user 
SET username=#{username},  
    password=#{password}, 
    age=#{age}, 
    phone=#{phone}, 
    email=#{email} 
WHERE id=#{id}

全行修改这个业务实际开发中几乎不会用到

但是对其中某一个列修改的业务又非常常见

我们不希望为买个列的单独修改都编写一个方法,所以希望编写一个方法

根据参数的情况,来修改不同的列

在UserMapper接口中编写代码如下

 //动态 if 修改
    Integer updateUserInfo(User user);

在UserMapper.xml文件中编写

<update id="updateUserInfo" parameterType="cn.tedu.entity.User">
        UPDATE t_user
        <!-- set标签会生成set关键字,还会自动去掉动态if部分产生的最后一个, -->
        <set>
            <!-- 当某个属性不为空时,表示要修改这个属性的值 -->
            <if test="username != null">
                username=#{username},
            </if>
            <if test="password !=null">
                password=#{password},
            </if>
            <if test="age != null">
                age=#{age},
            </if>
            <if test="phone != null">
                phone=#{phone},
            </if>
            <if test="email != null">
                email=#{email}
            </if>
        </set>
        WHERE id=#{id}
    </update>

测试一下

@Test
    public void testUpdate(){
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        User user=new User();
        user.setId(10);
        //user.setEmail("frank02@qq.com");
        //user.setAge(28);
        user.setPassword("4321");
        user.setPhone("18055500555");
        Integer num=mapper.updateUserInfo(user);
        System.out.println(num);
    }

动态参数查询

我们能经常看到下面的查询界面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o625LcRO-1614838631165)(C:/Users/juhui/Desktop/Java笔记/MyBatis/pvboxAhOLtSVXjRk.png!thumbnail)]

如果三个条一个都不写直接点查询:

执行

select * from t_user

如果写其中的一个条件点查询:

可能

select * from t_user where username like ?
select * from t_user where age=?
select * from t_user where phone like ?

如果写了其中两个或更多条件则与运行

select * from t_user where username like ? and age=?
.....

显然这个又一种动态sql语句拼接的情况

首先编写接口方法

//动态id 查询
    List<User> findUsersByParam(
            @Param("username")String username,
            @Param("age")Integer age,
            @Param("phone") String phone
    );

UserMapper.xml文件中

<!-- 动态查询  -->
    <select id="findUsersByParam" resultType="cn.tedu.entity.User">
        select
            id,username,password,age,phone,email
        from
            t_user
        <where>
            <if test="username != null">
                username like #{username}
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
            <if test="phone != null">
                and phone like #{phone}
            </if>
        </where>
    </select>

测试代码

@Test
    public void testSelect(){
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        List<User> list=mapper.findUsersByParam(
                "F%",null,"13%");
        for(User u: list){
            System.out.println(u);
        }

    }

表关系基础

数据库中的多张表可能存在关联关系

比如

公司部门表(t_department)和员工表(t_user)

  1. 一个部门有多个员工,一个员工只能属于一个部门

    这样情况就叫一对多(多对一)

    上面的情况是数据库中最常见的表关系

  2. 一个人只有一张身份证和一份档案

    一张身份证只能对应一份档案

    一份档案中只保存一个身份信息

    这种情况就是一对一

    3.在中小学校中,老师和学生的关系

​ 一个老师教多个学生

​ 一个学生被多个老师教

​ 上面的情况就是多对多

Mybatis实现关联查询

关联查询准备工作

我们创建一个部门表,再利用现有的t_user表形成一个一对多的关系

-- 创建 t_department 表
CREATE TABLE t_department (
 	id INT(11) AUTO_INCREMENT COMMENT '部门ID',
 	name VARCHAR(20) NOT NULL COMMENT '部门名',
 	PRIMARY KEY (id)
)DEFAULT CHARSET=utf8;

为表赋值

-- 在t_department表中插入数据
INSERT INTO t_department (name) VALUES ('Java'), ('C++'), ('Linux');

为t_user表新加一个部门id列

alter table t_user add column department_id int

为新加的列赋值

UPDATE t_user SET department_id=1 WHERE id<=7;

UPDATE t_user SET department_id=2 WHERE id>7;

添加外键(可选)

ALTER TABLE t_user
ADD CONSTRAINT dept_user FOREIGN KEY (department_id)
REFERENCES t_department(id)

使用值对象(vo)处理关联查询

现在需求查询如下信息

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SQF0Fxgq-1614838631167)(C:/Users/juhui/Desktop/Java笔记/MyBatis/D6yqI6EwTek51m8s.png!thumbnail)]

查询上面呃信息需要如下sql语句

SELECT u.id,username,d.name
 FROM t_user u
 LEFT JOIN  t_department d
 ON u.department_id=d.id

这样的查询结果,我们没有合适的实体类能接收

简单来讲我们可以为了这次查询创建一个合适的实体类

这种实体类称之为Vo(值对象)

创建cn.tedu.vo包,包中新建UserVO类

public class UserVO implements Serializable {
    private Integer id;
    private String username;
    private String departmentName;
	// 省略get\set\toString    
    
}

UserMapper接口新加方法

//关联查询(值对象查询)
List<UserVO> findUserDepartment();

UserMapper.xml文件

<select id="findUserDepartment" resultType="cn.tedu.vo.UserVO">
        SELECT
            u.id,
            username,
            d.name departmentname
        FROM
            t_user u
        LEFT JOIN
            t_department d
        ON
            u.department_id=d.id
    </select>

测试类代码

 // 关联查询(值对象)
    @Test
    public  void  getUserVO(){
        UserMapper mapper=ctx.getBean(
                "userMapper",UserMapper.class);
        List<UserVO> list=mapper.findUserDepartment();
        for(UserVO vo :list){
            System.out.println(vo);
        }
    }

使用一的一方处理关联查询

下面我们如果想查询出如下结果

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RcWIb0fs-1614838631171)(C:/Users/juhui/Desktop/Java笔记/MyBatis/0OEFSW1VBAUZATni.png!thumbnail)]

我们先创建cn.tedu.entity.Department

public class Department implements Serializable {

    private Integer id;
    private String name;

    private List<User> users;
    //省略get\set\toString
   
}

我们要执行的sql语句如下

按部门id查询这个部门信息和这个部门的所有员工

SELECT *
FROM t_department d
LEFT JOIN t_user u
ON d.id=u.department_id
WHERE d.id=1

由于下面的操作针对的是Department类,所以应该创建Department对应的Mapper和xml

创建DepartmentMapper接口,编写代码如下

public interface DepartmentMapper {

    //按id查询部门以及部门员工的信息
    Department findDeptWithUserById(Integer id);
}

创建DepartmentMapper.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="cn.tedu.mapper.DepartmentMapper">

    <!-- 下面是一个resultMap的自定义映射 -->
    <!--可以编写一个\多个查询结果中数据查询的列名对应java的属性名的关系 -->
    <resultMap id="deptMap" type="cn.tedu.entity.Department">
        <!-- 每个result标签表示一个列和一个java属性的对应关系 -->
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <!-- 当实体类中有List或类似集合类型对象时 -->
        <!-- 就使用collection来映射 -->
        <!-- ofType表明集合的泛型类型,property就是属性名 -->
        <collection property="users" ofType="cn.tedu.entity.User">
            <!--下面的映射对应的是User类的属性-->
            <result column="userId" property="id" />
            <result column="username" property="username"/>
            <result column="password" property="password"/>
            <result column="age" property="age"/>
            <result column="phone" property="phone"/>
            <result column="email" property="email"/>
        </collection>
    </resultMap>

    <select id="findDeptWithUserById" resultMap="deptMap">
        SELECT
            d.id,
            name,
            u.id userId,
            username,
            password,
            age,
            phone,
            email
        FROM t_department d
        LEFT JOIN t_user u
        ON d.id=u.department_id
        WHERE d.id=#{id}
    </select>
</mapper>

测试

 //关联查询(映射集合)
    @Test
    public void selectList(){
        DepartmentMapper mapper=ctx.getBean(
                "departmentMapper",DepartmentMapper.class);
        Department d=mapper.findDeptWithUserById(1);
        System.out.println(d);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值