MyBatis----Mybatis的参数、返回值深入

上一篇👉:MyBatis----基于代理 Dao 实现 CRUD 操作



🚴大家好!我是近视的脚踏实地,后边这系列主要是记录自己MyBatis的学习笔记,这篇文章主要来学习深入学习mybatis的参数、返回值
     唯有行动  才能解除你所有的不安

1、Mybatis的参数深入-使用实体类中的包装对象作为查询条件

之前我们已经学习了SQL语句的传参,使用标签的parameterType属性来设定。该属性的值可以是基本类型引用类型(例如:String),还可以是实体类类型(POJO 类),也就是我们说的javaBean,那么mybatis是使用ognl表达式解析对象字段的值,#{}和${}括号中的值是pojo及javaBean对象的属性名称,那么当然同时也可以是实体类包装类,那么下面我们将学习如何使用实体类的包装类作为参数传递。
小贴士1:
POJO的全称是Plain Old Java Object,普通的旧对象,它不能是某个类的子类、不能是某个接口的实现类、不能包含预先指定的注解。POJO对字段(属性)的访问和修改没有限制,它是一个封装了业务逻辑的对象,我们用控制器实现商业逻辑,通过操作POJO去访问数据库,POJO通常和数据库中的表拥有同样的字段。

Bean同样有以上要求(POJO的约束对Bean同样成立),但它另外有的就是要求属性是私有的、有无参构造方法、有getter和setter方法。Bean是POJO的一种,反之不成立。所有的Bean都应该实现Serializable接口。而POJO没有这项要求。

小贴士2:
OGNL表达式是 apache 提供的一种表达式语言,不仅在mybatis框架中有使用,在struts2也有使用,它的全称是Object Graphic Navigation Language 对象图导航语言,它是通过对象的取值方法来获取数据。在写法上把get给省略了,比如说我们获取用户的名称,类中的写法:user.getUsername,而OGNL表达式写法:user.username,它支持的这种写法就是根据这个属性名称就可以直接根据对象.出,那么usernam里边还要内容还可以继续的打点来去调,那么为什么mybatis中能直接写username,而不用你user.呢?因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名

那么我们在传递pojo对象的时候,可能这个pojo对象并不是我们想要的完整的或者全部的查询条件,一般在开发中我们的查询条件是综合的一个条件不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),那么这些条件我们可能都能组成一个对象,那么这个对象是我们自己定义的一个查询条件的对象,那么这个时候,在写查询方法的时候要把这个查询条件对象作为一个参数传递过去,这时可以使用包装对象传递输入参数。

那么比如我们在userdao接口中增加一个findUserByVo(QuerVo vo)方法👇:
在这里插入图片描述

那么在这里边,我们还是要使用模糊查询根据名称,只不过这个名称被封装到一个对象里,这个对象叫做QueryVo,然后里边定义了一个User类型的user,并且提供了它的get和set方法👇:

package monster.zf.domain;

/**
 * @author Monster丶ZF
 * @version 1.8
 * @remakeTodo
 * @Package monster.zf.domain
 * @date 2020/11/10 9:59
 */
public class QueryVo {
    private  User user;

    public User getUser() {
        return user;
    }

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

接着到UserDao.xml中进行配置
在这里插入图片描述

接着去编写测试类👇:
在这里插入图片描述
然后运行测试类👇:
在这里插入图片描述
此时仍然可以完成功能查询出来,这个就是我们通过实体类对象,再包一层,那这个也广泛应用在实际开发中,就是由多个对象来组成一个查询对象来实现数据的查询。

2、Mybatis的返回值深入-调整实体类属性解决增和改方法的报错

那么接着来学习结果类型的封装,就是我们的resultType可以规定我们的结果类型,那么结果类型可以一个int类型,也可以是一个pojo的对象,还可以是一个pojo的列表,那这里的pojo指的都是我们的实体类,换句话说就是它的结果可以是一个基本数据类型,像我们查询的记录条数一样,也可以是一个实体类对象,就是查询一个对象,也可以是一个实体类列表,也就是查询所有。

当我们使用查询的封装的时候,要求我们的实体类必须和数据库的字段列表保持一致,那么如果不一致呢?那下面来实验一下,首先把实体类User的字段名全都改了,和数据库的字段都不一样,然后重新生成get和set方法👇:

package monster.zf.domain;

import java.io.Serializable;
import java.util.Date;

/**
 * @author Monster丶ZF
 * @version 1.8
 * @remakeTodo
 * @Package monster.zf.domain
 * @date 2020/11/9 10:56
 */
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 + '\'' +
                '}';
    }
}

修改完实体类后,肯定就有很多地方报错了,但是这些都是一些可预见的错误,比如一些set和get方法的调用都会报错,所以接下来要一个一个地去改,那么来到测试中进行修改
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当然,还有一些错误是预见不到的,比如说userDao配置文件中就有错,这些错误是没有提示的,预见不到的,比如说这个keyProperty在实体类中不叫id了,而是叫userId,然后还在这里写id,那一定就会报错。
在这里插入图片描述
接着还有就是value,它找它的OGNL表达式,当它找不到了,它也一定会报错,所以这个时候我们的更新显然也是不能用了
在这里插入图片描述
那么可以先来运行下看看结果,比如说运行下保存操作
在这里插入图片描述
运行后肯定是报错的👇:,因为它根本就找不到它定义的哪些属性
在这里插入图片描述
所以这些属性我们都需要进行一个调整👇:
在这里插入图片描述
调整好后运行👇:,然后发现那个keyProperty的值还没有修改
在这里插入图片描述
所以需要把那个keyProperty的值改为userId,因为它对应的是实体类中属性的名称👇:
在这里插入图片描述
改完后在运行,就发现没有任何问题了
在这里插入图片描述
那么对于更新方法,我们也可以做一个改造,并且改造完成后也一定是可以用的,但是查询呢,查询方法能不能用呢,那么来运行findAll方法👇:
在这里插入图片描述
首选可以发现的是,不是所有的数据都能封装进去,而是除了name之外的内容都封装不进去,那么原因是什么呢,因为你所有的属性都没有对象,封装不进去,但是name为什么进去了呢,是因为mysql数据库在Window系统下不区分大小写,也就说它认为userNname和username是一回事,注意是mysql数据库,而不是你的java程序,所以说当mysql数据库取出来这个username的时候它可以跟userName进行一个匹配,所以就可以把这个封装进去,而其他的由于完全都不一样,所以无法封装,但是,如果是Linux操作系统,是严格区分大小写的,那么这个时候连name也封装不进去 ,这个就是为什么name有值,而其他属性没有原因。
在这里插入图片描述
在这里插入图片描述

3、Mybatis的返回值深入-解决实体类属性和数据库列名不对应的两种方式

那么现在有两种解决上述的问题的方案,这两个解决思路其实含义思路都是一样的,现在封装不进去的原因是它对不上,那么我们就要把它对得上就好了, 换句话说就是把数据库的字段和javaBean中的属性给他们一个一个地进行匹配,只要能匹配上那依然可以实现封装的功能

那么最最简单、最直接行使有效的就是起别名👇:当你起完别名的时候,就相当于你查询的结果,这个时候看到的内容又一次跟我们的实体类属性保持一致
在这里插入图片描述
那么运行测试一下👇:,然后发现我们的数据又都可以封装进去了,那么起别名的方式,我们用来解决这个问题是可以的,并且这种方式的执行效率也一定是最高的,因为它是在sql语句的层面上解决了问题。
在这里插入图片描述
当然mybatis还给我们提供了另外的解决思路,而这种解决思路并不需要起别名,而是采用配置的方式👇: ,那么这个配置使用的是一个叫做resultMap,它的id是一个唯一标识,我们可以随便写,接着他的类型标识标识的是它查询的对应实体类是哪个,里边就是配置的内容
在这里插入图片描述
那么当我们配置完后,然后去测试:👇
在这里插入图片描述
然后发现根本没有封装进去,是因为我们定义得很好,但是我们用了吗?那么当我们想使用这个结果类型对应的时候resultType就没有用了,而是需要用一个resultMap的属性,然后他指定的就是上边对应的id值
在这里插入图片描述
那么重新执行后发现可以成功封装了👇:
在这里插入图片描述

但是第二种的这个过程少不了要多解析几个标签,所以第二种这种解决方案显然在执行效率上没有第一种快,但是带来的好处就是开发的效率变快了,因为我们所有的查询方法都可以改成resultMap,只是引入的地方有些小改变,但是在后续的改造来说是很轻松的。
在这里插入图片描述那么如果在实际开发中追求执行效率,那毫无疑问,选择第一种方式,或者直接是把数据库的字段和实体的属性取名一模一样,那么如果你追求开发效率也是可以把实体类和你的数据库对应上,或者使用resultMap这种方式。


下一篇👉MyBatis----Mybatis传统 DAO 层开发

本篇博客到这就完啦,非常感谢您的阅读🙏,那么下一篇将会学习使用dao实现类来实现CRUD的功能,如果对您有帮助,可以帮忙点个赞或者来波关注鼓励一下喔😬

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值