Mybatis使用注解方式开发及Provider注解动态Sql开发

在这里插入图片描述

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为例)
  • controller:控制层
  
    @RestController
    @RequestMapping("/user")
    public class UserController {
        @Autowired
        private UserService userService;
    }
    
  • prop:实体类
	
	@Data
	public class User implements Serializable {
        private Long id;
        private String username;
        private String password;
        private String address;
        //一对多
        private List<Commodity> commodities;
	}

  • mapper:持久层

( PS:又称dao层,在jpa中叫做repository,在mybatis中叫做mapper )

@Mapper注解代表该类为dao层接口,也可以在启动类上添加注解@MapperScan根据路径扫描所有。

		
	@Mapper
    public interface UserMapper {
        
    }

  • service:业务层

    @Service注解表示该类为业务层,使当前类自动注入到spring容器中。

    
    @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文件的配置,通过注解的方式可快速实现对数据库的操作,过程比较简单好理解,具体高深的操作还需要开发人员多多专研,谢谢。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值