概述
考虑到基本数据类型在Java类中都有默认值,会导致Mybatis在执行相关操作时很难判断当前字段是否为null,所以在Mybatis环境下使用java实体类时尽量不要使用基本数据类型,都使用对应的包装类型。
环境搭建
常用注解
注解名称 | 用法 | 注意事项 |
---|---|---|
@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)方法时,有两种情况。
- 没有使用@Id注解明确指定主键字段。
select emp_id,emp_name,emp_salary from t_employee where emp_id = ? and emp_name = ? and emp_salary = ?
之所以会生成上面这样的where子句是因为tk将实体类中的所有字段都拿来放在一起作为联合主键查询。
- 使用@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字段作为查询条件。
- 测试实例
@Test
public void testSelect() {
UserEntity userEntity = new UserEntity();
userEntity.setUseName("张三");
userEntity.setPhone("");
userEntity.setAddress(null);
System.out.println(userMapper.select(userEntity));
}
- sql语句
==> Preparing: SELECT id,user_name,sex,age,address,phone FROM t_user WHERE user_name = ? AND phone = ?
==> Parameters: 张三(String), (String)
selectOne方法
xxxByPrimaryKey方法
需要使用@Id主键明确标记和数据库表主键字段对应的实体类字段,否则通用Mapper会将所有实体类字段作为联合主键。
xxxSelective方法
非主键字段如果为null值,则不加入sql语句中(包括返回字段和查询条件)。
插入
insert
tkmapper插入表中所以字段,没有赋值的字段使用null值。
- 测试示例
@Test
public void testInsert() {
UserEntity userEntity = new UserEntity();
userEntity.setUseName("张三1");
userEntity.setPhone("");
userEntity.setAddress(null);
userMapper.insert(userEntity);
}
- 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语句构造。
- 代码中只设置的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
通过主键更新对应记录中的除主键外的所有字段。
- 代码示例
@Test
public void testUpdate() {
UserEntity userEntity = new UserEntity();
userEntity.setId(1).setAddress("洛阳").setUseName("小华");
userMapper.updateByPrimaryKey(userEntity);
}
- 动态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构造。
- 代码示例
@Test
public void testUpdateSelective() {
UserEntity userEntity = new UserEntity();
userEntity.setId(40).setAddress("").setUseName("小华");
userMapper.updateByPrimaryKeySelective(userEntity);
}
- 动态sql
==> Preparing: UPDATE t_user SET user_name = ?,address = ? WHERE id = ?
==> Parameters: 小华(String), (String), 40(Integer)
删除
delete
tkmapper使用非null字段作为删除条件。
- 代码示例
@Test
public void testDelete() {
UserEntity userEntity = new UserEntity();
userEntity.setUseName("").setAge(18);
userMapper.delete(userEntity);
}
- 动态sql
==> Preparing: DELETE FROM t_user WHERE user_name = ? AND age = ?
==> Parameters: (String), 18(Integer)
deleteByPrimaryKey
可以直接使用主键值或者实体类作为参数。
- 代码示例
@Test
public void testDeleteByPrimaryKey() {
UserEntity userEntity = new UserEntity();
userEntity.setAge(18).setId(1);
// 使用实体类作为参数
userMapper.deleteByPrimaryKey(userEntity);
// 使用主键值作为参数
userMapper.deleteByPrimaryKey(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方法
该方法是大于特定值,某字段大于特定值并与上之前的查询条件,参数是实体类的某属性字段名、某属性字段值。
- 测试示例
@Test
public void testExample1() {
Example example = new Example(UserEntity.class);
example.createCriteria().andGreaterThan("useName", "张");
userMapper.selectByExample(example);
}
- 动态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)
- 示例代码
@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);
}
- 动态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字段
- 代码示例
@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);
}
- 动态sql
==> Preparing: SELECT distinct age , user_name FROM t_user order by age ASC,user_name DESC
==> Parameters:
分页查询
通过RowBounds来实现分页查询,指定开始和分页大小。
- 代码示例
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));
}
- 动态sql
SELECT prize FROM t_prize order by ? LIMIT ?, ?
==> Parameters: singleCont(String), 1(Integer), 10(Integer)
方法总结
参考
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100315.html