Data Access 之 MyBatis(三) - SQL Mapping XML(Part C)(上)

简介: Data Access 之 MyBatis(三) - SQL Mapping XML(Part C)

一、联合查询

resultMap自定义封装规则

当实体类属性和数据库字段的差异仅仅是 "_" 时,可以通过驼峰转换或者SQL语句中起别名的方式,如果属性和字段不一致,驼峰命名法就无法使用了,而起别名的方式较为繁琐,这时候就可以使用resultMap自定义封装规则

创建一张表t_cat

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_cat
-- ----------------------------
DROP TABLE IF EXISTS `t_cat`;
CREATE TABLE `t_cat` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cName` varchar(255) DEFAULT NULL,
  `cAge` int(2) DEFAULT NULL,
  `cgender` int(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_cat
-- ----------------------------
BEGIN;
INSERT INTO `t_cat` VALUES (1, '皮皮', 2, 0);
INSERT INTO `t_cat` VALUES (2, '六六', 1, 0);
INSERT INTO `t_cat` VALUES (3, '猪', 1, 0);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
复制代码

entity包中增加实体类Cat

@Data
public class Cat {
    private Integer id;
    private String name;
    private Integer gender;
    private Integer age;
}
复制代码

dai包中增加CatDao接口

public interface CatDao {
    Cat getCatById(Integer id);
}
复制代码

mappers目录下增加SQL映射文件cat.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="com.citi.dao.CatDao">
    <!--参数类型不用写-->
    <select id="getCatById" resultType="com.citi.entity.Cat">
        select * from t_cat where id = #{id}
    </select>
</mapper>
复制代码

将cat.xml注册到MyBatis全局配置文件中

<mappers>
    <mapper resource="mappers/employee.xml"/>
    <mapper resource="mappers/cat.xml"/>
</mappers>
复制代码

生成CatDaoTest测试类

public class CatDaoTest {
    SqlSessionFactory sqlSessionFactory = null;
    SqlSession openSession = null;
    @Before
    public void setUp() throws Exception {
        //1、根据全局配置文件创建出一个SqlSessionFactory
        //SqlSessionFactory:是SqlSession工厂,负责创建SqlSession对象;
        //SqlSession:sql会话(代表和数据库的一次会话);
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        openSession = sqlSessionFactory.openSession();
    }
    @Test
    public void getCatById() {
        CatDao catDao = openSession.getMapper(CatDao.class);
        Cat cat = catDao.getCatById(1);
        System.out.println(cat);
    }
}
复制代码

执行测试方法

c4403ce5758f4ffa95bc5c3fb44c8bb1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

除了ID,其余属性都是null,MyBatis默认可以自动封装结果集,但前提是数据库字段和属性值一一对应(不区分大小写),出现这种情况的原因是数据库的字段和实体类属性不一致,导致对象的部分属性赋值失败。如果数据库字段和实体类属性名字的区别只是有无下划线,那么可以在MyBatis全局配置文件中开启驼峰命名法来解决。如果完全不一致则有两种解决办法。

第一种解决办法是在查询SQL中给查询的字段起别名,使之与实体类属性名一致。修改映射文件

<select id="getCatById" resultType="com.citi.entity.Cat">
    select id, cname name, cage age, cgender gender from t_cat where id = #{id}
</select>
复制代码

再次执行测试

65a3d61e815f4b99a26e7ce6ccf398d4_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

第二种方法是使用resultMap标签自定义结果集,实现数据库字段和实体类属性的对应,resultType和resultMap是互斥的,使用了resultMap就不要再使用resultType

<select id="getCatById" resultMap="mycat">
    select * from t_cat where id = #{id}
</select>
<resultMap id="mycat" type="com.citi.entity.Cat">
    <!--定义主键映射规则-->
    <id property="id" column="id"></id>
    <!--普通列的映射规则-->
    <result property="gender" column="cgender"></result>
    <result property="age" column="cage"></result>
    <result property="name" column="cname"></result>
</resultMap>
复制代码
  • type:指定为哪一个实体类自定义封装规则,全类名
  • id:唯一标识,被其他引用
  • column:指定的数据库的字段
  • property:指的是实体类的属性
  • result:标签用来定义非主键列的映射规则

执行测试

e3e0966ed3aa41d19993e8ab26900f76_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

联合查询

由于实体类和数据库表是一一对应的,当进行联合查询时没有哪一个实体类可以与联合查询的结果一一对应,这时就可以使用resultMap来封装联合查询的结果

一对一查询

在entity包中新增两个实体类Key、Lock,两者为一对一关系

@Data
public class Key {
    private Integer id;
    private String keyName;
    // 能打开的锁
    private Lock lock;
}
复制代码
@Data
public class Lock {
    private Integer id;
    private String lockName;
}
复制代码

创建数据库表,并通过外键建立关联关系,并插入两条数据

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_key
-- ----------------------------
DROP TABLE IF EXISTS `t_key`;
CREATE TABLE `t_key` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `keyname` varchar(255) DEFAULT NULL,
  `lockid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_key_lock` (`lockid`),
  CONSTRAINT `fk_key_lock` FOREIGN KEY (`lockid`) REFERENCES `t_lock` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for t_lock
-- ----------------------------
DROP TABLE IF EXISTS `t_lock`;
CREATE TABLE `t_lock` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `lockName` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
复制代码

在dao包中新建KeyDao接口

public interface KeyDao {
    Key getKeyById(Integer id);
}
复制代码

在mappers中新增key.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="com.citi.dao.KeyDao">
    <!--参数类型不用写-->
    <select id="getKeyById" resultMap="mykey">
        SELECT k.id,k.keyname,k.lockid, l.id lid, l.lockname
        FROM t_key k
        LEFT JOIN t_lock l ON k.lockid = l.id
        WHERE k.id = #{id}
    </select>
    <resultMap id="mykey" type="com.citi.entity.Key">
        <id property="id" column="id"></id>
        <result property="keyName" column="keyname"></result>
        <result property="lock.id" column="lid"></result>
        <result property="lock.lockName" column="lockName"></result>
    </resultMap>
</mapper>
复制代码

SQL查询语句建议使用left Join,不易错。多表联合查询一定要使用resultMap,自定封装规则。这里使用级联属性获取key中所包含的lock的属性

在全局配置文件中注册key.xml

<mappers>
    <mapper resource="mappers/employee.xml"/>
    <mapper resource="mappers/cat.xml"/>
    <mapper resource="mappers/key.xml"/>
</mappers>
复制代码

增加测试类KeyDaoTest

public class KeyDaoTest {
    SqlSessionFactory sqlSessionFactory = null;
    SqlSession openSession = null;
    @Before
    public void setUp() throws Exception {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        openSession = sqlSessionFactory.openSession();
    }
    @Test
    public void getKeyById() {
        KeyDao keyDao = openSession.getMapper(KeyDao.class);
        Key key = keyDao.getKeyById(1);
        System.out.println(key);
    }
}
复制代码

执行测试

81b4f632c6334ad7a4f5a2568e21649d_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

上述方式使用到了级联属性,而MyBatis推荐使用association属性来完成自定义封装规则

修改resultMap

<resultMap id="mykey" type="com.citi.entity.Key">
    <id property="id" column="id"></id>
    <result property="keyName" column="keyname"></result>
    <!--<result property="lock.id" column="lid"></result>-->
    <!--<result property="lock.lockName" column="lockName"></result>-->
    <association property="lock" javaType="com.citi.entity.Lock">
        <id property="id" column="id"></id>
        <result property="lockName" column="lockName"></result>
    </association>
</resultMap>
复制代码
  • association:定义一个复杂类型的关联
  • javaType:指定对象的类型

再次执行测试

19ac7a48b6ef45a78bd696297d8b9e9e_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

一对多查询

在数据库表中新增数据一个3号锁,有多把钥匙可以打开3号锁,也就是说一把锁有多把钥匙,这就形成了一对多的关系

修改Lock实体类,增加钥匙列表的属性

@Data
public class Lock {
    private Integer id;
    private String lockName;
    private List<Key> keyList;
}
复制代码

一对一和一对多的区别在于所站的角度不同,一对多是外键建立在多的一方,多对多时通过中间表建立关系

在dao包中新建LockDao

public interface LockDao {
    Lock getLockById(Integer id);
}



相关文章
|
6月前
|
XML Java 数据库连接
mybatis中在xml文件中通用查询结果列如何使用
mybatis中在xml文件中通用查询结果列如何使用
385 0
|
3月前
|
XML SQL 数据格式
XML动态sql查询当前时间之前的信息报错
XML动态sql查询当前时间之前的信息报错
52 2
|
6月前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
59 0
|
5月前
|
XML Java 数据库连接
MyBatis入门——MyBatis XML配置文件(3)
MyBatis入门——MyBatis XML配置文件(3)
64 6
|
30天前
|
SQL 存储 机器学习/深度学习
将 AWS Data Lake 和 S3 与 SQL Server 结合使用
将 AWS Data Lake 和 S3 与 SQL Server 结合使用
41 0
|
2月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
44 1
|
5月前
|
SQL XML 数据库
后端数据库开发高级之通过在xml文件中映射实现动态SQL
后端数据库开发高级之通过在xml文件中映射实现动态SQL
50 3
|
5月前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
70 3
|
4月前
|
XML Java 数据格式
支付系统----微信支付20---创建案例项目--集成Mybatis-plus的补充,target下只有接口的编译文件,xml文件了,添加日志的写法
支付系统----微信支付20---创建案例项目--集成Mybatis-plus的补充,target下只有接口的编译文件,xml文件了,添加日志的写法
|
5月前
|
XML Java 数据库连接
MyBatis第二课,灰度发布,@Results注解,使用xml书写mysql
MyBatis第二课,灰度发布,@Results注解,使用xml书写mysql