天天看点

SpingBoot整合jdbctemplate/MyBatis/Srping Data-比较

文章目录

        • 概念
        • 1.SpringBoot+jdbctemplate
        • 2.SpringBoot+MyBatis
        • 3.SpringBoot+Spring Date JPA

SpringBoot提供的数据持久层的解决方案:

  1. SpringBoot+jdbctemplate(用的很少,自己demo用用挺好,轻量级,功能比较少)
  2. SpringBoot+MyBatis(实际开发中使用最多)
  3. SpringBoot+Spring Date JPA(没有2用的多,它的优点可能就在于它是Spring整个体系下提供的,并且支持ORM,因为底层基于Hibernate实现的,自动完成实体类和表的映射,就不用像MyBatis那样手动完成映射了。)

概念

1.Hibernate:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。属于全自动的ORM框架,着力点在于POJO和数据库表之间的映射,完成映射即可自动生成和执行sql。

2.Mybatis:MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。属于半自动的ORM框架,着力点在于POJO和SQL之间的映射,自己编写sql语句,然后通过配置文件将所需的参数和返回的字段映射到POJO。

3.Spring Data JPA:Spring Data是一个通过命名规范简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。

1.SpringBoot+jdbctemplate

JdbcTemplate 是 Spring 自带的 JDBC 模版组件,底层实现了对 JDBC 的封装,⽤用法与 MyBatis 类似,开发者需要⾃自定义 SQL 语句句,JdbcTemplate 帮助开发者完成数据库连接,SQL 执⾏,以及结果集的解析。

目录结构:

SpingBoot整合jdbctemplate/MyBatis/Srping Data-比较

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.southwind</groupId>
    <artifactId>jdbctemplate</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>
           

entity:

@Data
public class Student {
    private int id;
    private String name;
}

           

数据层:

public interface StudentRepository {
    Student findById(int id);
}
           
@Repository
public class StudengRepositoryImpl implements StudentRepository {

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Override
    public Student findById(int id) {
        //三个参数:1.sql。2.参数数组。3.BeanPropertyRowMapper是RowMapper的实现类。RowMapper是一个接口,作用是解析结果集,将sql查询出的ResultSet对象转换为泛型指定的java对象。
        return jdbcTemplate.queryForObject("select * from student where id = ?",new Object[]{id},new BeanPropertyRowMapper<Student>(Student.class));
    }
}
           

controller层:

@RestController
public class StudentHandler {

    @Autowired
    StudentRepository studentRepository;

    @GetMapping("/findById/{id}")
    public Student findById(@PathVariable("id") int id){
        return studentRepository.findById(id);
    }
}
           

Application启动类:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}
           

配置文件:

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

数据库部分就建了个Student表。

上面代码复制即可运行。

因为jdbc现实中很少使用的,所以就curd就不具体写了。

可以注意的是:

JdbcTemplate 对基本的 CRUD 操作提供了了良好的⽀支持,通过调⽤用 query 和 update ⽅方法即完成相关操作,其中 query 是⽤用来做查询操作的,update 是⽤用来做添加、删除、修改功能。

1、queryForObject(String sql,Object[] args,RowMapper rowMapper),查询⼀条记录,并且将结果集封装成 Java 对象。

2、query(String sql,RowMapper rowMapper),查询⼀组数据,并且将结果集封装成集合对象。RowMapper 是⼀个接⼝,作⽤就是解析结果集,将 JDBC 查询出的 ResultSet 对象转换为对应的 Java对象,在调⽤用该对象时需要指定目标类的结构,泛型。

update(String sql, Object… args)

参数:1、要执⾏的 SQL 语句。2、可变参数 Object…args,满⾜参数的可变性。

客户端⽤?传参 key-value 形式将数据传给 Spring MVC 服务端,业务方法的形参列表不需要添加任何注解即可自动封装参数 Java 对象。

客户端传 JSON 格式数据,业务⽅法的形参列表需要添加 @RequestBody 注解,才能封装参数 Java 对象。

业务方法的参数的注解形式比较:

@PathVariable:

@GetMapping("/findById/{id}")
    public Student findById(@PathVariable("id") int id){
        return studentRepository.findById(id);
    }
           

访问服务的url格式:http://localhost:8080/findById/1

@RequestParam:

@GetMapping("/findById")
    public Student findById(@RequestParam int id){
        return studentRepository.findById(id);
    }
           

访问服务的url格式:http://localhost:8080/findById?id=1,当然@RequestParam:是可以省略的!

@RequestBody:

@GetMapping("/saveByStu")
    public Student findById(@RequestBody Student stu){
        return studentRepository.findById(stu);
    }
           

访问服务的url格式:http://localhost:8080/saveByStu,我是用postman测试的,传入josn格式的数据。如果不写这个注解,是数据添加不进去的。因为参数压根就没有解析拿到。

2.SpringBoot+MyBatis

目录结构:

SpingBoot整合jdbctemplate/MyBatis/Srping Data-比较

与jdbcTemplate相比,MyBatis主要区别在于不用再java中写sql语句,而是用xml语句完成,灵活性和扩展性更好。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>www.gosang</groupId>
    <artifactId>springbootMyBatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
           

application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC
    username: root
    password: xxxx
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: /mapping/*.xml
  type-aliases-package: com.gosang.entity
           

配置了实体类和mapping的映射。

Application

package com.gosang;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.gosang.repository")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}
           

启动类与jdbc不同的是加了@MapperScan(“com.gosang.repository”),扫描,把这些代理类交给Spring管理。

其他的业务代码就大差不差了。如下:

StudentRepository.java

public interface StudentRepository {
    List<Student> findAll();
    Student findById(int id);

    void save(Student student);
    void update(Student student);
    void delete(int id);
}
           

StudentRepository.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gosang.repository.StudentRepository">
    <select id="findAll" resultType="Student">
        select * from student
    </select>

    <select id = "findById" parameterType = "int" resultType = "Student">
        select * from Student where id = #{id}
    </select>

    <insert id="save" parameterType="Student">
        insert into Student(name) VALUES (#{name});
    </insert>

    <update id="update" parameterType="Student">
        update Student set name = #{name} where id = #{id}
    </update>

    <delete id="delete" parameterType="int">
        delete from Student where id = #{id}
    </delete>
</mapper>
           

StudentHandler.java

@RestController
public class StudentHandler {

    @Autowired
    StudentRepository studentRepository;

    @GetMapping("/findAll")
    public List<Student> fingAll(){
        return studentRepository.findAll();
    }

    @GetMapping("/findById")
    public Student findById(int id){
        return studentRepository.findById(id);
    }

    @PostMapping("/save")
    public void save(@RequestBody Student student){
        studentRepository.save(student);
    }

    @PutMapping("/update")
    public void update(@RequestBody Student student){
        studentRepository.update(student);
    }

    @DeleteMapping("/delete")
    public void delete(int id){
        studentRepository.delete(id);
    }
}

           

同上在postman中去测试。

http://localhost:8080/findAll

http://localhost:8080/findById?id=1

SpingBoot整合jdbctemplate/MyBatis/Srping Data-比较
SpingBoot整合jdbctemplate/MyBatis/Srping Data-比较

**小结:**与jdbc那种在java文件中写sql式的硬编码方式相比MyBatis就显得更加灵活,耦合度更低。

3.SpringBoot+Spring Date JPA

Spring Date JPA是Spring提供的持久层解决方案,但它本身并不是一个具体的实现,它是比较上层的封装,底层还是基于Hibernate。

虽然JdbcTemplate同样是Spring提供的,但他只是一个模板。Spring Date JPA是一个体系更大的基于Hibernate的持久层实现。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.southwind</groupId>
    <artifactId>springboot+springdatajpa</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>
           

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: xxx
    url: jdbc:mysql://localhost:3306/mybatis
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true
           

Application

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}
           

entity实体类

@Data
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private String name;
}

           

这里实体类的写法就和前两种有所区别了。能自动完成映射这些注解少不了。

StudentRepository

public interface StudentRepository extends JpaRepository<Student,Long> {
    public Student findByName(String name);
}
           

用这个方案和Hibernate一样,连sql语句都不用写了,都是JpaRepository会提供的。我们只要继承这个接口就可以使用的,开箱即用。要注意的是,起名字一定要规范,才能自动识别到对应类型的sql。如public Student findByName(String name);。

StudentHandler

@RestController
public class StudentHandler {
    @Autowired
    private StudentRepository studentRepository;

    @GetMapping("/findAll")
    public List<Student> findAll(){
        return studentRepository.findAll();
    }

    @GetMapping("/findById/{id}")
    public Student findById(@PathVariable("id") Long id){
        return studentRepository.findById(id).get();
    }

    @PostMapping("/save")
    public void save(@RequestBody Student student){
        studentRepository.save(student);
    }

    @PutMapping("/update")
    public void update(@RequestBody Student student){
        studentRepository.save(student);
    }

    @DeleteMapping("/deleteById/{id}")
    public void deleteById(@PathVariable("id") Long id){
        studentRepository.deleteById(id);
    }

    @GetMapping("/findByName/{name}")
    public Student findByName(@PathVariable("name") String name){
        return studentRepository.findByName(name);
    }
}
           

继续阅读