从零学 spring cloud第3-3课:数据库基础之MyBatis

什么是MyBatis

    项目的DEMO代码:https://github.com/heyu52/-spring-cloud
    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。这里我主要讲的是注解方式。
官方参考文档:http://www.mybatis.org/mybatis-3/zh/index.html

特点

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。

创建项目

SQL中我们选择mybatis与Mysql,stringboot 的版本2.1.6
在这里插入图片描述

配置数据库连接

spring.datasource.url=jdbc:mysql://localhost:3306/Spring?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=csdn
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

项目可以运行起来没有报错。数据库我们依然是使用上节的数据库。

创建Model

package com.csdn.demo.model;
public class User {
    private Long id;
    private String name;
    private int age;
    private String sex;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return ("id=" + this.id + "name=" + this.name + ",age=" + this.age + ",pass=" + this.sex);
    }

    public User() {

    }

    public User(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
}

指定实体类路径

我要在 application.properties 中要指定model包的位置
增加一个配置项:

mybatis.type-aliases-package=com.csdn.demo.model

建接口Mapper

我们新增一个查询用户的接口方法,注意里面脚本使用了传参。在 SQL 中使用 #{id} 来接收同名参数。

package com.csdn.demo.mapper;

import com.csdn.demo.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper {

    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(Long id);

}

#打印执行脚本
logging.level.com.csdn.demo.mapper=debug

新建Controller

package com.csdn.demo.web;

import com.csdn.demo.mapper.UserMapper;
import com.csdn.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/getUserById")
    public User getList(long id) {
        User user=userMapper.getUserById(id);
        return user;
    }

}

运行项目,浏览器输入:http://127.0.0.1:8080/getUserById?id=13
在这里插入图片描述
结果就是我们想要的了。
上面我们的数据库表的列名和我们类的名字是一致的,所以可以返回完整的实体,但是,如果我们的表的列名和类的属性定义不一样,那我们应该使用下面的方式来使之对应起来。

    @Select("SELECT * FROM user WHERE id = #{id}")
    @Results({
            @Result(property = "name", column = "name")
    })
    User getUserById(Long id);

我们增加Results注解,可以指定model属性和数据表的列对应关系。

@Param

当我们的参数和脚本的参数不一致时,我们要使用@Param
我们新增一个接口方法

 @Select("SELECT * FROM user WHERE sex = #{sex} and age > #{age}")
    List<User> getUserByNameAndAge(@Param("sex") String userSex, @Param("age") int userage);

UserController中新增测试方法

   @RequestMapping("/getUserByNameAndAge")
    public  List<User> getUserByNameAndAge(String userSex, int userage) {
        List<User> users=userMapper.getUserByNameAndAge(userSex,userage);
        return users;
    }

运行项目,浏览器输入:http://127.0.0.1:8080/getUserByNameAndAge?userSex=%E7%94%B7&userage=10
查找大于10岁的男用户
在这里插入图片描述

@Map

如果参数不能确实有多少个,我们可以使用Map来传递。
新增map接口方法

    @Select("SELECT * FROM user WHERE sex = #{sex} and age > #{age}")
    List<User> getUserByMapParam(Map<String,Object> args);

新增UserController方法

 @RequestMapping("/getUserByMapParam")
    public  List<User> getUserByMapParam() {

        Map param=  new HashMap();
        param.put("sex","女");
        param.put("age",10);

        List<User> users=userMapper.getUserByMapParam(param);
        return users;
    }

运行项目,浏览器输入:http://127.0.0.1:8080/getUserByMapParam
在这里插入图片描述

传递实体对象

我们新创建一个插入用户的接口方法

    @Insert("INSERT INTO user(name,sex,age) VALUES(#{name}, #{sex}, #{age})")
    void insertUser(User user);

新增UserController方法

 @RequestMapping("/insertUser")
    public int getList() {
        User user = new User();
        user.setName("20190630");
        user.setSex("男");
        user.setAge(99);
        userMapper.insertUser(user);
        return 1;
    }

运行项目,浏览器输入:http://127.0.0.1:8080/insertUser
在这里插入图片描述
在执行时,系统会自动读取对象的属性并值赋到同名的 #{xxx} 中。

前面用到了@Select,@Insert,当然我们肯定能想到,还有@Update,@Delete
我在DEMO中会给出例子,这里就不再细述了,用法和上面基本一致。

接口方法

    @Update("UPDATE user SET name=#{name}  WHERE id =#{id}")
    void updateUser(User user);

    @Delete("DELETE FROM user WHERE id =#{id}")
    void deleteUser(Long id);

UserController

    @RequestMapping("/updateUser")
    public int updateUser() {
        User user = new User();
        user.setId(13L);
        user.setName("201906302123");
        userMapper.updateUser(user);
        return 1;
    }

    @RequestMapping("/deleteUser")
    public int deleteUser() {
        userMapper.deleteUser(12L);
        return 1;
    }

动态 SQL的实现

MyBatis 最大的特点是可以灵活的支持动态 SQL,在注解版中提供了两种方式来支持,第一种是使用注解来实现,另一种是提供 SQL 类来支持。

注解
接口方法

   @Update({"<script> ",
            "update user  " ,
            "<set>" ,
            " <if test='name != null'>name=#{name},</if>" ,
            " <if test='age > 99 '>age=#{age},</if>" ,
            " </set> ",
            "where id=#{id} " ,
            "</script>"})
    void updateUserByScript(User user);

UserController

    @RequestMapping("/updateUserByScript")
    public int updateUserByScript() {
        User user = new User();
        user.setId(13L);
        user.setName("2019");
        user.setAge(100);
        userMapper.updateUserByScript(user);
        return 1;
    }

这种方式写起来很痛苦,不推荐。

SQL 构建类
新增UserParam类

package com.csdn.demo.mapper;

public class UserParam {
    private String userName;

    private String userSex;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }
}

新增UserSql类

package com.csdn.demo.mapper;

import org.apache.ibatis.jdbc.SQL;
import org.springframework.util.StringUtils;
public class UserSql {

    public String getUserCount(UserParam userParam) {
        String sql = new SQL() {{
            SELECT("COUNT(1)");
            FROM("user");
            if (!StringUtils.isEmpty((userParam.getUserName()))) {
                WHERE("name=#{userName}");
            }
            if (!StringUtils.isEmpty((userParam.getUserSex()))) {
                WHERE("sex=#{userSex}");
            }
        }}.toString();
        System.out.println("sql :" + sql);
        return sql;
    }
}

接口方法

  @SelectProvider(type = UserSql.class, method = "getUserCount")
    int getUserCount(UserParam userParam);

UserController

    @RequestMapping("/getUserCount")
    public long getUserCount() {
        UserParam userParam=new UserParam();
        userParam.setUserName("csdn");
        userParam.setUserSex("男");

        long count=userMapper.getUserCount(userParam);
        return  count;
    }

运行项目,浏览器输入:http://127.0.0.1:8080/getUserCount
在这里插入图片描述
说实话,这两种方式都好费劲。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值