文章目录
Mybatis(注解方式)
什么是mybatis?
- MyBatis 是一款优秀的持久层框架。
- 它支持自定义 SQL、存储过程以及高级映射。
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。、
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
(一)常用注解
注解 | 说明 |
---|---|
@Insert | 增加 |
@Update | 删除 |
@Delete | 修改 |
@Select | 查询 |
@Result | 结果集封装 |
@Results | 结果集多个封装 |
@ResultMap | 引用@Results 定义的封装 |
@One | 一对一结果集封装 |
@Many | 一对多结果集封装 |
@CacheNamespace | 注解二级缓存 |
@SelectProvider | 动态 SQL 映射 |
(二)数据库准备
user
用户表(无任何外键,作为主表使用)
-
account
账户余额表(uid关联user表主键,实现一对一查询) -
commodity
商品表(uid关联user表主键,实现一对多查询)
(三)快速使用
1、相关依赖
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
2、项目结构(user为例)
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
}
@Data
public class User implements Serializable {
private Long id;
private String username;
private String password;
private String address;
//一对多
private List<Commodity> commodities;
}
( PS:又称dao层,在jpa中叫做repository,在mybatis中叫做mapper )
@Mapper注解代表该类为dao层接口,也可以在启动类上添加注解@MapperScan根据路径扫描所有。
@Mapper
public interface UserMapper {
}
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
}
3、单表增删改查
- 首先在dao层UserMapper接口中定义增删改查的方法。
// 增加一个用户
@Insert("insert into user(username ,password ,address) values(#{usernmae},#
{password},#{address})")
void insertUser(User user);
// 删除一个用户
@Delete("delete from user where id=#{id}")
void deleteUser(Long id);
// 修改一个用户
@Update("update user set username =#{username}, password=#{password},address=#
{address} where id=#{id}")
void updateUser(User user);
// 查询所有用户
@Select("select * from user")
List<User> findUser();
- 其次在业务层UserService类中实现UserMapper接口并重写方法
@Override
public void insertUser(User user) {
userMapper.insertUser(user);
}
@Override
public void deleteUser(Long id) {
userMapper.deleteUser(id);
}
@Override
public void updateUser(User user) {
userMapper.updateUser(user);
}
@Override
public List<User> findUser() {
return userMapper.findUser();
}
- 最后在控制层UserController书写映射地址和方法
@PostMapping("/insertUser")
public void insertUser(User user) {
userService.insertUser(user);
}
@DeleteMapping("/delUser/{id:\\d+}")
public void delUser(@PathVariable Long id) {
userService.deleteUser(id);
}
@PutMapping("/updateUser")
public void updateUser(User user) {
userService.updateUser(user);
}
@GetMapping("/findUser")
public List<User> findUser() {
return userService.findUser();
}
3、多表一对一,一对多查询
-
首先新增prop实体类的一对一和一对多的属性
@JsonIgnore
注解代表json序列化时将一些属性忽略掉,不生成属性
@Data
public class User implements Serializable {
private Long id;
private String username;
@JsonIgnore
private String password;
private String address;
//一对一
private Account account;
//一对多
private List<Commodity> commodities;
}
-
其次在dao数据交互层UserMapper中重新书写返回的对象方法
@Results
代表对多个结果集的封装,@Result
而是对单个结果集的封装,映射User的全部属性
@Select("select * from user")
@Results({
@Result(id = true ,column = "id" ,property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(column = "address",property = "address"),
@Result(property = "account",column = "id",
one=@One(select = "com.demo.mybatisdemo.mapper.AccountMapper.findAccountByUid")),
@Result(property = "commodities",column = "id",
many = @Many(select = "com.demo.mybatisdemo.mapper.CommodityMapper.findCommodityByUid"))
})
List<User> findAllUser();
@One
定义后映射到一对一的AccountMapper的另一条查询语句
@Select("select * from account where uid=#{uid}")
List<Account> findAccountByUid(Long id);
@Many
定义后映射到一对多的CommodityMapper的另一条查询语句
@Select("select * from commodity where uid=#{uid}")
List<Commodity> findCommodityByUid(Long id);
- 其次在Service业务层UserService中重写方法
@Override
public List<User> findAllUser() {
return userMapper.findAllUser();
}
- 最后在Controler控制层书写映射地址后调用注入的UserService方法
// 查询用户的所有商品和余额
@GetMapping("/findAllUser")
public List<User> findAllUser() {
return userService.findAllUser();
}
4、效果展示
(四)provider动态sql
1、注解介绍
注解 | 说明 |
---|---|
@InsertProvider | 自定义的provider类构造SQL语句—增加 |
@DeleteProvider | 自定义的provider类构造SQL语句—删除 |
@UpdateProvider | 自定义的provider类构造SQL语句—修改 |
@SelectProvider | 自定义的provider类构造SQL语句—查询 |
2、创建辅助类Provider
- 对象需要赋值给注解中的type属性
- 方法名对应注解中的method属性
- 返回值就是要执行的sql
public class UserProvider {
}
3、增加Mapper方法
- @增删改查Provider注解代表了使用自定义的构造SQL语句。
- type属性代表要和哪个类相对应,method代表要和对象里的哪个方法相对应。
@Mapper
public interface UserMapper {
@InsertProvider(type = UserProvider.class, method = "saveUserProvider")
void saveUserProvider(User user);
@DeleteProvider(type = UserProvider.class,method = "delUserProviderById")
void delUserProviderById(@Param("id") Long id);
@UpdateProvider(type = UserProvider.class,method = "updateUserProviderById")
void updateUserProviderById(User user);
@SelectProvider(type = UserProvider.class, method = "listUserProvider")
@ResultMap("userAccountAndCommodity")
List<User> listUserProvider(@Param("user") User user);
}
4、书写Provider方法
1)@InsertProvider
// 动态插入用户
public String saveUserProvider(User user) {
return new SQL() {
{
INSERT_INTO("user");
if (user.getUsername() != null && !user.getUsername().equals(" ")) {
VALUES("username", "#{username}");
}
if (user.getPassword() != null && !user.getPassword().equals(" ")) {
VALUES("password", "#{password}");
}
if (user.getAddress() != null && !user.getAddress().equals(" ")) {
VALUES("address", "#{address}");
}
}
}.toString();
}
2)@DeleteProvider
// 动态删除用户根据id
public String delUserProviderById(Long id) {
return new SQL() {
{
DELETE_FROM("user");
WHERE("id=#{id}");
}
}.toString();
}
3)@UpdateProvider
// 动态修改用户根据id
public String updateUserProviderById(User user) {
return new SQL() {
{
UPDATE("user");
if (user.getUsername() != null && !user.getUsername().equals(" ")) {
SET("username=#{username}");
}
if (user.getPassword() != null && !user.getPassword().equals(" ")) {
SET("passwprd=#{password}");
}
if (user.getAddress() != null && !user.getAddress().equals(" ")) {
SET("address=#{address}");
}
WHERE("id=#{id}");
}
}.toString();
}
4)@SelectProvider
// 第二种方法追加sql语句(多表)
public String listUserProvider(User user) {
return new SQL() {
{
SELECT("*");
FROM("user");
LEFT_OUTER_JOIN("account on account.uid = user.id");
LEFT_OUTER_JOIN("commodity on commodity.uid = user.id ");
GROUP_BY("user.username");
if (user.getUsername() != null) {
WHERE("username=#{user.username}");
}
if (user.getAddress() != null) {
WHERE("address=#{user.address}");
}
if (user.getAccount() != null && user.getAccount().getMoney() != null) {
WHERE("money>=#{user.account.money}");
}
}
}.toString();
}
5、业务层跳转
public void saveUserProvider(User user){
userMapper.saveUserProvider(user);
}
public void delUserProviderById(Long id){
userMapper.delUserProviderById(id);
}
public void updateUserProviderById(User user){
userMapper.updateUserProviderById(user);
}
public List<User> listUserProvider(User user) {
return userMapper.listUserProvider(user);
}
6、控制层请求
@PostMapping("/saveUserProvider")
public String saveUserProvider(User user){
userService.saveUserProvider(user);
return "动态插入成功";
}
@DeleteMapping("/delUserProvider/{id}")
public String delUserProviderById(@PathVariable Long id){
userService.delUserProviderById(id);
return "动态删除成功";
}
@PutMapping("/updateUserProviderById")
public String updateUserProviderById(User user){
userService.updateUserProviderById(user);
return "动态修改成功";
}
@GetMapping("/findUserProvider")
public List<User> listUserProvider(User user){
return userService.listUserProvider(user);
}
可以根据postman测试工具测试:根据多个查询得条件返回符合条件得用户信息
总结:Mabati注解方式避免了xml文件的配置,通过注解的方式可快速实现对数据库的操作,过程比较简单好理解,具体高深的操作还需要开发人员多多专研,谢谢。