美文网首页springbootSpring Boot全家桶
Spring Boot数据库交互之Spring Data JPA

Spring Boot数据库交互之Spring Data JPA

作者: 狄仁杰666 | 来源:发表于2020-06-30 19:16 被阅读0次

    Spring Data JPA介绍
    Spring Boot中支持的数据库交互方式多种多样,今天咱就来玩一下Spring Data JPA好了,因为其他的,咱也还不会呀!?!

    JPA全称为Java Persistence API(Java持久层API),它是Sun公司在JavaEE 5中提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具,来管理Java应用中的关系数据,JPA吸取了目前Java持久化技术的优点,旨在规范、简化Java对象的持久化工作。很多ORM框架都是实现了JPA的规范,如:Hibernate、EclipseLink。

    Spring Data JPA旨在通过减少实际需要的工作量来显著改善数据访问层的实现。它在JPA的基础上做了一些封装,可以轻松实现基于JPA的存储库。 此模块处理对基于JPA的数据访问层的增强支持。 它使构建使用数据访问技术的Spring驱动应用程序变得更加容易。

    需要注意的是JPA统一了Java应用程序访问ORM框架的规范

    JPA为我们提供了以下规范:

    1. ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
    2. JPA 的API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发人员不用再写SQL了(只能说在一定程度上不用写SQL,实际情况可能还是会用一些SQL);
    3. JPQL查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合;

    以上的定义引用自网络技术文章,我还在不断理解与学习中,我们先来Demo一个例子:

    P.S.:本演示是基于上期文章创建的项目演进的:

    5分钟入手Spring Boot

    集成Spring Data JPA
    以连接Oracle为例(网上有很多Mysql的案例,除了配置不一样,其实使用差不多,有机会我们可以Demo Mysql、Mongo的案例)
    在项目pom.xml中的dependencies节点加入以下依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc8</artifactId>
        <version>12.2.0.1.0</version>
    </dependency>
    

    准备数据库配置

    1. 在src/main底下创建resources文件夹;

    2. 在resources文件夹内新建application.properties文件;


      resources
    3. 在application.properties文件内输入数据库的配置信息,如:

    spring.datasource.url=jdbc:oracle:thin:@//xxdb-scan:xxxx/XXXX
    spring.datasource.username=xxxx
    spring.datasource.password=xxxxxxxx
    spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
    spring.jpa.show-sql=true
    spring.jackson.serialization.indent_output=true
    
    1. 启动项目,验证数据库配置正确与否;


      启动项目 1
      启动项目 2

    创建实体类entity
    假设我们的数据库中有个表叫LEAD表(也叫lead表),我们想查询LEAD表中的数据;

    1. 创建entity包;
    2. 在entity包内创建实体类Lead.java;


      实体类
    3. 编写实体类;
      (LEAD 表有多个字段,我们本例只使用其中的2个字段,一个是lead_id, 一个是email;)
    package com.mycompany.sample.entity;
    
    import javax.persistence.*;
    
    /**
     * @author : dylanz
     * @since : 06/30/2020
     **/
    @Entity
    @Table(name = "LEAD")
    public class Lead {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "lead_id")
        private int leadId;
        @Column(name = "email")
        private String email;
    
        public Lead() {
        }
    
        public Lead(Integer leadId, String email) {
            this.leadId = leadId;
            this.email = email;
        }
    
        public int getLeadId() {
            return leadId;
        }
    
        public void setLeadId(int leadId) {
            this.leadId = leadId;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    #@Table(name = "LEAD")这个非必需,当未提供时,说明本实体类的表名是实体类类名转换后的名字,如:
    # 1.实体类名为Lead时,默认表名为:lead表;
    # 2.实体类名为UserPermission时,默认表名为:user_permission表;
    #@Column(name = "lead_id")中name为非必需,当未提供时,说明数据库的列名为对应成员变量转换后的名字,如:
    # 1.当对应的成员变量为private int leadId; 时,默认数据库列名为lead_id;
    # 2.当对应的成员变量为private int email; 时,默认数据库列名为email;
    #可以看到,实体类和成员变量均为驼峰结构,而对应的表明和数据库列名为下划线结构;
    #尽管如此,还是建议补全@Table和@Column;
    #Spring Boot还有很多注解和属性,可以用于规范实体类及实体类的列,比如长度限制、数据类型限制等,
    #这里不再详细介绍,毕竟我们本例的重点不是介绍这个。
    

    创建repository
    有了实体类之后,我们接下来要创建一个repository接口类,并在repository接口类内实现数据库交互,并且把交互结果映射到实体类Lead.java

    1. 创建repository包;
    2. 在repository包内创建repository接口类LeadRepository.java;


      repository接口类
    3. 编写repository接口类;
    package com.mycompany.sample.repository;
    
    import com.mycompany.sample.entity.Lead;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.stereotype.Repository;
    
    import javax.transaction.Transactional;
    
    /**
     * @author : dylanz
     * @since : 06/30/2020
     **/
    @Repository
    public interface LeadRepository extends JpaRepository<Lead, Integer> {
        @Query(value = "select l from Lead l where leadId=?1")
        Lead getLeadByLeadId(Integer leadId);
    
        @Query(value = "select lead_id,email from lead where lead_id=?1", nativeQuery = true)
        Lead getLeadByLeadIdWithNativeQuery(Integer leadId);
    
        @Modifying
        @Query(value = "update lead set email=?1 where lead_id=?2", nativeQuery = true)
        @Transactional
        void updateLeadEmail(String email, Integer leadId);
    }
    #增、删、改的数据库交互,必须搭配@Modifying使用,并且建议也使用注解@Transactional来处理事务,
    #即交互失败,Spring Boot会自动帮我们进行回滚。
    

    创建service
    repository创建完之后,我们就可以与数据库进行交互了,接下来我们写个service调用repository

    1. 创建service包;
    2. 创建service类;


      service类
    3. 编写service类;
    package com.mycompany.sample.service;
    
    import com.mycompany.sample.entity.Lead;
    import com.mycompany.sample.repository.LeadRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @author : dylanz
     * @since : 06/30/2020
     **/
    @Service
    public class LeadService {
        @Autowired
        private LeadRepository leadRepository;
    
        public Lead getLead(Integer leadId) {
            return leadRepository.getLeadByLeadId(leadId);
        }
    
        public Lead getLeadByLeadIdWithNativeQuery(Integer leadId) {
            return leadRepository.getLeadByLeadIdWithNativeQuery(leadId);
        }
    
        public Lead updateEmail(com.mycompany.sample.domain.Lead lead) {
            int leadId = lead.getLeadId();
            String email = lead.getEmail();
            leadRepository.updateLeadEmail(email, leadId);
            Lead updatedLead = leadRepository.getLeadByLeadId(leadId);
    
            if (updatedLead.getEmail() != null && !updatedLead.getEmail().equals(email)) {
                throw new InternalError("Unable to update email for leadId: " + leadId + " with email: " + email);
            }
            return updatedLead;
        }
    }
    

    开发带数据库交互功能的API
    service开发完成后,我们要把该service暴露给客户端使用,于是就要创建API了

    1. 创建Controller;


      Controller
    2. 编写Controller;
    package com.mycompany.sample.controller;
    
    import com.mycompany.sample.entity.Lead;
    import com.mycompany.sample.service.LeadService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @author : dylanz
     * @since : 06/30/2020
     **/
    @RestController
    public class LeadController {
        @Autowired
        private LeadService leadService;
    
        @GetMapping("/getLead/{leadId}")
        @ResponseBody
        public Lead getLead(@PathVariable Integer leadId) {
            return leadService.getLead(leadId);
        }
    
        @GetMapping("/getLead")
        @ResponseBody
        public Lead getLeadById(@RequestParam("leadId") Integer leadId) {
            return leadService.getLeadByLeadIdWithNativeQuery(leadId);
        }
    
        @PutMapping(value = "/updateLeadEmail")
        @ResponseBody
        public Lead updateLeadEmail(@RequestBody com.mycompany.sample.domain.Lead lead) {
            return leadService.updateEmail(lead);
        }
    }
    
    1. 为了演示PUT请求,我还建了个updateLeadEmail API,并且引入lombok;
    • pom.xml中dependencies节点内添加lombok依赖
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
        <scope>provided</scope>
    </dependency>
    
    • 建立domain包;
    • 编写Lead domain;
    package com.mycompany.sample.domain;
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * @author : dylanz
     * @since : 06/30/2020
     **/
    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Lead implements Serializable {
        private static final long serialVersionUID = 1L;
    
        private Integer leadId;
        private String email;
    }
    

    运行Spring Boot项目,见证奇迹

    调用Get API,返回执行结果:

    http://127.0.0.1:8080/getLead?leadId=10xxxx46http://127.0.0.1:8080/getLead/10xxxx46

    API交互结果 1
    API交互结果 2

    调用Put API,返回执行结果:

    API交互结果 3
    1. 同时项目log中,我们可以找到被执行的sql:
      为了能看到sql,关键一步是src/main/resources/application.properties内的配置项:spring.jpa.show-sql=true
      后台log

    其中第一条SQL是非nativeQuery的,第二、三条SQL是nativeQuery的,nativeQuery的SQL就是我们平常写的sql,而非nativeQuery的SQL,是Spring Boot JPA帮我们生成的。

    到此为止,我们已经完成了Spring Boot项目中采用Spring Boot JPA方式与数据库交互的实现!

    码字不容易,点赞需积极

    谢谢!!!

    相关文章

      网友评论

        本文标题:Spring Boot数据库交互之Spring Data JPA

        本文链接:https://www.haomeiwen.com/subject/ugdofktx.html