tkMybatis基本用法(二)

导读:本篇文章讲解 tkMybatis基本用法(二),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

概述

考虑到基本数据类型在Java类中都有默认值,会导致Mybatis在执行相关操作时很难判断当前字段是否为null,所以在Mybatis环境下使用java实体类时尽量不要使用基本数据类型,都使用对应的包装类型。

环境搭建

参考:
tkMybatis与springboot整合(一)

常用注解

注解名称 用法 注意事项
@Table 建立实体类和数据表之间的映射关系,在@Table注解的name属性中指定数据表的名称。 如果@Table中不指定name,默认规则:实体类名首字母小写作为表名(Employee类对应employee表)
@Column 建立实体类属性和表字段之间的映射关系,在@Column注解的name属性中指定表字段名。 @Column不指定name,默认属性的驼峰命名对应表字段的“_”,比如:parentId对应表字段parent_id。
@Id 标识数据表的主键。 作用于xxxByPrimaryKey(xxx)方法。
@GeneratedValue 让tk在执行insert操作之后将数据库字段生成的主键值回写到实体类对象中。 表中主键需要是自增主键、或序列主键。
@Transient 用于标记不与数据表字段对应的实体类字段 与数据表不相关,tk生成的动态sql不涉及该属性。

@Id注解

通用Mapper在执行xxxByPrimaryKey(param)方法时,有两种情况。

  1. 没有使用@Id注解明确指定主键字段。
select emp_id,emp_name,emp_salary from t_employee where emp_id = ? and emp_name = ? and emp_salary = ?

之所以会生成上面这样的where子句是因为tk将实体类中的所有字段都拿来放在一起作为联合主键查询。

  1. 使用@Id注解明确标记和数据库表中主键字段对应的实体类属性
    例如注解在empId属性上:
select emp_id,emp_name,emp_salary from t_employee where emp_id = ?

@GeneratedValue

作用:让通用Mapper在执行insert操作之后将数据库自动生成的主键值回写到实体类对象中。

  • 自增主键用法
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer empId;
  • 序列主键用法
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY, generator = "select SEQ_ID.nextval from dual")
private Integer id;

@Transient 主键

用于标记不与数据库表字段对应的实体类字段。

@Transient
private String otherThings; // 非数据库表中字段

设计演示使用的t_user表和实体类

t_user表

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`
(
    `id`        int NOT NULL AUTO_INCREMENT,
    `user_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
    `age`       int                                  DEFAULT NULL,
    `sex`       tinyint                              DEFAULT NULL COMMENT "0:男,1:女",
    `address`   varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
    `phone`     varchar(11)                          default null,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

映射t_user表的UserEntity实体类

@Data
@Accessors(chain = true)
@Table(name = "t_user")
public class UserEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    private Integer id;

    @Column(name = "user_name")
    private String useName;

    private Integer sex;

    private Integer age;

    private String address;

    private String phone;
}

基本的CRUD

查询

select

tkmapper使用实体类中的非null字段作为查询条件。

  1. 测试实例
    @Test
    public void testSelect() {
        UserEntity userEntity = new UserEntity();
        userEntity.setUseName("张三");
        userEntity.setPhone("");
        userEntity.setAddress(null);
        System.out.println(userMapper.select(userEntity));
    }
  1. sql语句
==>  Preparing: SELECT id,user_name,sex,age,address,phone FROM t_user WHERE user_name = ? AND phone = ? 
==> Parameters: 张三(String), (String)

selectOne方法

通用Mapper替我们自动生成的SQL语句情况。
在这里插入图片描述

  1. 实体类封装查询条件生成where子句的规则。
    • 使用非null的值生成where子句。
    • 在条件表达式中使用 “=” 进行比较。
  2. 要求必须返回一个实体类结果,如果有多个,则会抛出异常。
    在这里插入图片描述

xxxByPrimaryKey方法

需要使用@Id主键明确标记和数据库表主键字段对应的实体类字段,否则通用Mapper会将所有实体类字段作为联合主键。

xxxSelective方法

非主键字段如果为null值,则不加入sql语句中(包括返回字段和查询条件)。

插入

insert

tkmapper插入表中所以字段,没有赋值的字段使用null值。

  1. 测试示例
    @Test
    public void testInsert() {
        UserEntity userEntity = new UserEntity();
        userEntity.setUseName("张三1");
        userEntity.setPhone("");
        userEntity.setAddress(null);
        userMapper.insert(userEntity);
    }
  1. sql语句
==>  Preparing: INSERT INTO t_user ( id,user_name,sex,age,address,phone ) VALUES( ?,?,?,?,?,? ) 
==> Parameters: null, 张三1(String), null, null, null, (String)
<==    Updates: 1

insertList

批量插入数据,tkmapper插入表中所以字段,没有赋值的字段使用null值。
插入条件:限制实体包含id属性并且必须为自增列。
测试示例:

        List<Person> personEntities = new ArrayList<>();
        ...
        if (CollectionUtils.isNotEmpty(personEntities )) {
            personMapper.insertList(personEntities);
        }

insertSelective

如果字段为null值(“”或者其它空值会参与sql构造),则不加入sql语句中,也就是非null的字段参与sql语句构造。

  1. 代码中只设置的useName,age,address,sex其他都为默认值null。
        UserEntity userEntity = new UserEntity();
        userEntity.setUseName("李思").setAge(18).setAddress("南京").setSex(1);
==>  Preparing: INSERT INTO t_user ( user_name,sex,age,address ) VALUES( ?,?,?,? ) 
==> Parameters: 李思(String), 1(Integer), 18(Integer), 南京(String)
<==    Updates: 1

更新

updateByPrimaryKey

通过主键更新对应记录中的除主键外的所有字段。

  1. 代码示例
    @Test
    public void testUpdate() {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(1).setAddress("洛阳").setUseName("小华");
        userMapper.updateByPrimaryKey(userEntity);
    }
  1. 动态sql
==>  Preparing: UPDATE t_user SET user_name = ?,sex = ?,age = ?,address = ?,phone = ? WHERE id = ? 
==> Parameters: 小华(String), null, null, 洛阳(String), null, 1(Integer)

updateByPrimaryKeySelective

通过主键更新对应记录中的非null字段的值,null字段不参与sql构造。

  1. 代码示例
    @Test
    public void testUpdateSelective() {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(40).setAddress("").setUseName("小华");
        userMapper.updateByPrimaryKeySelective(userEntity);
    }
  1. 动态sql
==>  Preparing: UPDATE t_user SET user_name = ?,address = ? WHERE id = ? 
==> Parameters: 小华(String), (String), 40(Integer)

删除

delete

tkmapper使用非null字段作为删除条件。

  1. 代码示例
    @Test
    public void testDelete() {
        UserEntity userEntity = new UserEntity();
        userEntity.setUseName("").setAge(18);
        userMapper.delete(userEntity);
    }
  1. 动态sql
==>  Preparing: DELETE FROM t_user WHERE user_name = ? AND age = ? 
==> Parameters: (String), 18(Integer)

deleteByPrimaryKey

可以直接使用主键值或者实体类作为参数。

  1. 代码示例
    @Test
    public void testDeleteByPrimaryKey() {
        UserEntity userEntity = new UserEntity();
        userEntity.setAge(18).setId(1);
        // 使用实体类作为参数
        userMapper.deleteByPrimaryKey(userEntity);

        // 使用主键值作为参数
        userMapper.deleteByPrimaryKey(1);
    }
  1. 动态sql
==>  Preparing: DELETE FROM t_user WHERE id = ? 
==> Parameters: 1(Integer)

QBC查询(条件Example用法)

上面都是单表最简单的CRUD,但是稍微复杂一些的单表查询无能为力了,这时候是条件查询Example大显身手的时候了。
查询原理:通过实体类属性名称反查出数据表对于的column字段,然后用这些column字段作为查询条件构成动态sql。

概念

Query By Criteria:通过条件查询。
criteria是Criterion的复数形式。意思是:规则、标准、准则。在SQL语句中相当于查询条件。
QBC查询是将查询条件通过java对象进行模块化封装。

andGreaterThan方法

该方法是大于特定值,某字段大于特定值并与上之前的查询条件,参数是实体类的某属性字段名、某属性字段值。

  1. 测试示例
    @Test
    public void testExample1() {
        Example example = new Example(UserEntity.class);
        example.createCriteria().andGreaterThan("useName", "张");
        userMapper.selectByExample(example);
    }
  1. 动态sql
==>  Preparing: SELECT id,user_name,sex,age,address,phone FROM t_user WHERE ( ( user_name > ? ) ) 
==> Parameters: 张(String)

QBC拼装 where (age > 18 and sex = 1) or ( age < 30 and sex = 0)

  1. 示例代码
    @Test
    public void testCriteria1() {
        Example example = new Example(UserEntity.class);
        // 新增条件1
        Example.Criteria criteria1 = example.createCriteria();
        criteria1.andGreaterThan("age", 18).andEqualTo("sex", 1);
        // 新增条件2
        Example.Criteria criteria2 = example.createCriteria();
        criteria2.andLessThan("age", 30).andEqualTo("sex", 0);

        // 设计不是很合理,example不应该代表criteria1与criteria2进行逻辑OR
        example.or(criteria2);
        userMapper.selectByExample(example);
    }
  1. 动态sql
==>  Preparing: SELECT id,user_name,sex,age,address,phone FROM t_user WHERE ( ( age > ? and sex = ? ) or ( age < ? and sex = ? ) ) 
==> Parameters: 18(Integer), 1(Integer), 30(Integer), 0(Integer)

sql排序、去重、设置select字段

  1. 代码示例
    @Test
    public void testExample() {
        Example example = new Example(UserEntity.class);
        // 设置排序字段
        example.orderBy("age").asc().orderBy("useName").desc();
        // 设置去重
        example.setDistinct(true);
        // 设置select 子句的字段
        example.selectProperties("age", "useName");

        userMapper.selectByExample(example);
    }
  1. 动态sql
==>  Preparing: SELECT distinct age , user_name FROM t_user order by age ASC,user_name DESC 
==> Parameters: 

分页查询

通过RowBounds来实现分页查询,指定开始和分页大小。

  1. 代码示例
public Result getPageByEvent(Paging paging, String eventId) {
        // 这是分页
        RowBounds rowBounds = new RowBounds(paging.getPageNum(), paging.getPageSize());
        // new一个Example
        Example example = new Example(Prize.class);
        // 排序
        example.orderBy("singleCont").asc();
        // 添加条件
        Example.Criteria criteria = example.createCriteria();
        // 前面 一个参数对应实体类的 属性,后一个对应 要传的值
        criteria.andEqualTo("eventId", eventId);
        List<Prize> prizes = prizeMapper.selectByExampleAndRowBounds(example, rowBounds);
        return Result.success(new PageInfo<Prize>(prizes));
    }
  1. 动态sql
SELECT prize FROM t_prize order by ? LIMIT ?, ?
==> Parameters: singleCont(String), 1(Integer), 10(Integer)

方法总结

参考

TkMybatis笔记

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100315.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!