目录
【K】Mybatis使用@Select注解书写简单sql
【K】MySQL 数据类型与 Java 类型的对应关系
【K】Mybatis相同代码复用
1. 定义公共 SQL 片段
2. 引用公共 SQL 片段
3. 使用参数
4. 复用和组合
5. 注意事项
【K】mysql如何实现插入一条数据后立刻获取该数据自增长id进行调用
背景解析
代码使用
【K】Mybatis新增数据,存在就更新,不存在就添加
常规方法
Replace关键字
【K】MyBatis执行多个sql语句
背景
代码举例
实例举例
分析总结
【K】Mybatis 不同条件拼接不同sql
举例1
举例2: 判断某一个值
举例3
【K】-IFNULL处理N/A
背景知识
SQL语句分析
改进后的SQL语句
知识扩展
注意事项
【K】Mybatis条件查询<where>标签
【K】使用resultMap封装对象一对多
数据库模型
实体类
MyBatis 配置
举例
【K】Mybatis使用常见类型的类型别名
//1. 基本查询
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUserById(int id);
//2. 动态查询
@Select("")
List selectUsersById(@Param("id") Integer id);
//3. 返回 Map
@Select("SELECT * FROM users")
@MapKey("id")
Map selectUsersAsMap();
//4. 使用注解参数
@Select("SELECT * FROM ${tableName}")
List selectUsersFromTable(@Param("tableName") String tableName);
//5. 结果映射
@Select("SELECT id, name, email FROM users WHERE id = #{id}")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "name", column = "name"),
@Result(property = "email", column = "email")
})
User selectUserDetailedById(int id);
//6. 联合查询
@Select("SELECT u.id, u.name, a.city FROM users u INNER JOIN address a ON u.id = a.user_id WHERE u.id = #{id}")
User selectUserWithAddress(int id);
//7. 分页查询
@Select("SELECT * FROM users LIMIT #{limit} OFFSET #{offset}")
List selectUsersByPage(@Param("limit") int limit, @Param("offset") int offset);
在 MyBatis 中,Java 类型和 MySQL 数据库类型之间的映射是通过 `typeHandlers` 来实现的。以下是一些常见的 MySQL 数据类型与 Java 类型的对应关系,以及在 MyBatis 的 XML 配置文件中如何配置它们的示例。
MySQL 数据类型 | Java 类型 | MyBatis XML 配置中的类型别名 |
---|---|---|
CHAR |
String |
VARCHAR |
VARCHAR |
String |
VARCHAR |
BLOB |
byte[] |
BLOB |
TEXT |
String |
VARCHAR |
INTEGER |
int /Integer |
INTEGER |
TINYINT |
byte /Byte |
TINYINT |
SMALLINT |
short /Short |
SMALLINT |
MEDIUMINT |
int /Integer |
INTEGER |
BIGINT |
long /Long |
BIGINT |
FLOAT |
float /Float |
FLOAT |
DOUBLE |
double /Double |
DOUBLE |
DECIMAL |
java.math.BigDecimal |
DECIMAL |
DATE |
java.sql.Date |
DATE |
TIME |
java.sql.Time |
TIME |
DATETIME |
java.sql.Timestamp |
TIMESTAMP |
TIMESTAMP |
java.sql.Timestamp |
TIMESTAMP |
BOOLEAN |
boolean /Boolean |
BOOLEAN |
ENUM |
String |
VARCHAR |
SET |
String |
VARCHAR |
在 MyBatis 的配置文件 `mybatis-config.xml` 中,你不需要为每种类型映射都显式定义 `typeHandler`,因为 MyBatis 已经内置了对这些常见类型的处理。但如果你需要自定义类型处理器,你可以这样配置:
以下是一个包含所有类型映射的 MyBatis 映射文件 (`UserMapper.xml`) 示例:
在这个示例中,`
请注意,实际开发中可能不需要为每个字段都显式指定 `jdbcType`,因为 MyBatis 通常能够推断出对应的类型。但在某些情况下,特别是当 MyBatis 无法准确推断类型时(例如对于 `null` 值),指定 `jdbcType` 可以避免类型相关的错误。
在 MyBatis 中,为了避免重复编写相同的 SQL 片段,可以使用 `
使用 `
AND id = #{id}
在实际的查询语句中,使用 `
在公共 SQL 片段中,可以使用 MyBatis 的参数占位符 `#{}` 来引用传入的参数。确保传入的参数名称与 `
可以将多个 `
- 确保 `
- 在 `
- 当在 `
通过这种方式,可以有效地管理和复用 SQL 代码,减少冗余,并使得 SQL 语句的维护变得更加简单。
useGeneratedKeys 取值范围true|false 默认值是:false。
含义:设置是否使用JDBC的.
getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。
insert into user (name, age)
values ( #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER})
@Override
@Transactional(readOnly = false)
public int insertUser() {
User user = new User();
user.setName("why");
user.setAge(18);
int count = userMapper.insert(user);
System.out.println(count); // 插入的条数:1
int id = user.getId();
System.out.println(id); // 自增的id:666
return id;
}
先查询是否存在,存在就更新,不存在就添加.
如果数据量过大, 使用foreach批量操作
举例: 集合唯一索引 id
可以查询所有的id集合idSet, 使用in idSet查询那些存在, 返回结果集oldSet.
然后遍历判断idSet是否存在oldSet, 存在走更新逻辑,不存在走添加逻辑.
REPLACE关键字的使用
使用REPLACE的最大好处就是可以将DELETE和INSERT合二为一,形成一个原子操作。这样就可以不必考虑在同时使用DELETE和INSERT时添加事务等复杂操作了。
在使用REPLACE时,表中必须有唯一索引,而且这个索引所在的字段不能允许空值,否则REPLACE就和INSERT完全一样的。
在执行REPLACE后,系统返回了所影响的行数,如果返回1,说明没有重复的记录,如果返回2,说明有重复记录,系统先DELETE这条记录,然后再INSERT这条记录。
语法和INSERT非常的相似,如下面的REPLACE语句是插入或更新一条记录。
REPLACE INTO users (id,name,age) VALUES(1, '李嘉欣', 18);
驱动默认不开启支持多个sql执行。
在数据库连接的url增加参数allowMultiQueries,值为true,多个SQL直接一以“;”分隔即可
xxx.jdbcUrl=jdbc:mysql://xx.xx.xx:3306/xxxxx?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true
&allowMultiQueries=true
场景:
删除用户的时候需要先删除用户的外键关联数据,否则会触发规则报错。
本人遇到的是循环拼接不同字段条件的修改sql执行。
直接写多条语句,用“;”隔开即可
delete from sec_user_role where userId=#{id};
delete from sec_user where id=#{id};
执行多个SQL查询并返回多个结果集的原因简述:
MyBatis执行多个查询并处理结果集的方法简述:
总结:
MyBatis支持一次执行多个SQL查询并返回多个结果集,这有助于优化性能和提升代码质量。
在MyBatis中,可以使用动态SQL功能来根据不同的条件拼接不同的SQL语句。动态SQL是MyBatis的一大特色,它允许在XML映射文件中构建灵活的SQL语句。主要通过
以下是一个使用MyBatis动态SQL的例子,我们将创建一个根据不同条件来查询用户的例子。
首先,定义一个User对象和一个UserMapper接口:
// User.java
public class User {
private Integer id;
private String name;
private String email;
// getters and setters...
}
// UserMapper.java
public interface UserMapper {
List findUsers(Map params);
}
然后,在MyBatis的XML映射文件中,我们定义动态SQL查询:
在这个例子中,
现在,当我们调用findUsers方法时,可以传递一个包含id、name、email等键的Map对象。MyBatis会根据Map中的键值对是否存在来动态构建SQL语句。
// 使用MyBatis的SqlSession来执行查询
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map params = new HashMap<>();
params.put("name", "John Doe");
List users = mapper.findUsers(params);
// 处理查询结果...
} finally {
sqlSession.close();
}
在上面的Java代码中,我们创建了一个包含"name"键的Map,并将其作为参数传递给findUsers方法。MyBatis会生成一个包含AND name = 'John Doe'条件的SQL语句,因为Map中只有"name"键。
不同条件拼接不同sql
ORDER BY
dept DESC
type DESC
Postman访问
注意事项
前言:
name代码为String,
XML 代码为:
某些特殊业务场景下的, 为了替换#{demoWay}的替换写法...
#{demoStr} ]]>
= #{demoStr} ]]>
这种动态SQL的方法使得SQL语句的构建非常灵活,可以根据传入的参数不同构建不同的查询条件,而不必编写多个几乎相同的查询语句。这样的设计既简化了代码,也使得维护更加容易。
在数据库中,有时需要生成具有特定格式的唯一ID。例如,这里的ID由当前日期(格式为yyyymmdd)和一个顺序号(四位数)组成。每当需要添加新的记录时,就要生成一个新的ID,该ID比当天已有的最大ID大1。
原始的SQL语句试图获取当天最大的ID,然后将其加1以生成新的ID。如果当天没有ID,就默认使用'0001'
作为顺序号。
公司表获取最大ID且加1:
ID示例:yyyymmdd+0001
SELECT
IFNULL(RIGHT(ac.id + 1, 4), '0001') numMax
FROM
app_company ac
WHERE
LEFT(ac.id, 8) = DATE_FORMAT(now(), '%Y%m%d')
ORDER BY
RIGHT(ac.id, 4) DESC
LIMIT 1
这个查询有几个问题:
改进后的SQL语句使用MAX函数来找出当天最大的ID,然后通过IFNULL处理当天没有任何ID的情况。这样就不需要ORDER BY和LIMIT子句,因为MAX函数已经能够找到最大的ID。
SELECT
IFNULL(MAX(RIGHT(ac.id, 4)) + 1, '0001') numMax
FROM
app_company ac
WHERE
LEFT(ac.id, 8) = DATE_FORMAT(now(), '%Y%m%d')
在实际使用中,直接在数据库层面进行ID的生成可能会有并发问题,特别是在高并发的环境下。为了确保ID的唯一性和顺序,可能需要采用其他机制,比如应用层的锁或者使用数据库的序列(在MySQL 8.0+中为AUTO_INCREMENT属性)。
此外,如果ac.id是字符型字段,直接进行+ 1操作可能会导致错误,因为字符型和数值型的操作不同。在这种情况下,可能需要先将ID的顺序号部分转换为数值型,进行加法操作后再转换回字符型。
MyBatis 的
如果
如果
示例:
假设我们有一个 User 表,包含 id、name、email 等字段,现在我们要根据这些字段的不同组合来查询用户。
UserMapper 接口:
public interface UserMapper {
List findUsers(Map params);
}
UserMapper.xml 映射文件:
在上述例子中:
这种方式确保了 WHERE 条件的灵活性和正确性,同时避免了手动编写复杂的逻辑来控制 SQL 语句的准确性。使用
在 MyBatis 中,`resultMap` 是一个非常强大的映射工具,它能够处理复杂的数据库关系,如一对一、一对多和多对多的关系。通过正确使用 `resultMap`,可以在执行单个查询时获取关联的数据,而不必执行多次查询,这样可以提高应用程序的性能。
下面是一个使用 `resultMap` 来处理一对一和一对多关系的完整示例。
假设我们有以下三个表:
1. 用户表 `user`
2. 部门表 `department`
3. 用户联系人表 `user_linkman`
用户表(user):
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`age` int(2) unsigned DEFAULT NULL,
`department_id` int(11) NOT NULL COMMENT '部门id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
部门表(department):
CREATE TABLE `department` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门id',
`department_name` varchar(255) DEFAULT NULL COMMENT '部门名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='部门表';
用户联系人表(user_linkman):
CREATE TABLE `user_linkman` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户联系人表主键id',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`linkman_id` varchar(255) DEFAULT NULL COMMENT '联系人id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='用户联系人表';
用户实体类(User):
package com.example.demo.entity;
import lombok.Data;
import java.util.List;
@Data
public class User {
private String id;
private String code;
private String name;
private int age;
private Department department; // 对应部门实体
private List linkmenList; // 对应联系人列表
}
在 MyBatis 的映射文件中,我们可以定义一个 `resultMap` 来描述如何从数据库结果集映射到我们的实体类。
在上述配置中,我们定义了一个 `userResultMap`:
- `
- `
通过这种配置,当我们调用 `selectUserById` 查询时,MyBatis 会自动执行 `selectDepartmentById` 和 `selectLinkmanListByUserId` 查询来填充 `User` 实体中的 `department` 和 `linkmenList` 属性。
假设我们需要查询某次考试的所有单位信息,包括名称、参考人数、通过人数、通过率,以及本部门所有参考人员的信息。我们可以创建一个对应的 `resultMap`:
这里的 `
MyBatis 提供了一系列内置的类型别名,用于简化 XML 配置文件中的类型引用。这些别名代表了 Java 中的一些常见类型。使用类型别名可以让你的 MyBatis 配置文件更加简洁易懂。
下面是一些常见的 MyBatis 内置类型别名及其对应的 Java 类型:
Java 类型 | MyBatis 别名 |
---|---|
byte | _byte |
long | _long |
short | _short |
int | _int |
Integer | _integer |
double | _double |
float | _float |
boolean | _boolean |
还有一些引用类型的别名:
Java 类型 | MyBatis 别名 |
---|---|
String | string |
Byte | byte |
Long | long |
Short | short |
Integer | int |
Double | double |
Float | float |
Boolean | boolean |
Date | date |
BigDecimal | decimal |
BigDecimal | bigdecimal |
Object | object |
Map | map |
HashMap | hashmap |
List | list |
ArrayList | arraylist |
Collection | collection |
Iterator | iterator |
使用这些类型别名的例子:
在上述例子中,`resultType="_int"` 表示查询的结果是一个基本类型 `int`,`resultType="string"` 表示查询的结果是 `String` 类型,而 `resultType="map"` 表示查询的结果是 `Map` 类型的集合。
要注意的是,当我们使用类型别名 `_int` 时,通常是在查询返回单个值的场景,比如统计数量或者查询某个特定的数值
有用请点赞,养成良好习惯!
疑问、交流、鼓励请留言!