1. 程式人生 > >spring boot2 整合(二)JPA(特別完整!)

spring boot2 整合(二)JPA(特別完整!)

JPA全稱Java Persistence API.JPA通過JDK 5.0註解或XML描述物件-關係表的對映關係,並將執行期的實體物件持久化到資料庫中。

JPA 的目標之一是制定一個可以由很多供應商實現的API,並且開發人員可以編碼來實現該API,而不是使用私有供應商特有的API。

JPA是需要Provider來實現其功能的,Hibernate就是JPA Provider中很強的一個,應該說無人能出其右。從功能上來說,JPA就是Hibernate功能的一個子集。

本教程大概流程:
1. 藉助idea實現springboot 和 spring data jpa 整合
2. 實現JpaRepository介面快捷開發
3. 自定義Mapper查詢介面方法
4. MVC架構+分頁功能實戰
5. QueryDSL工具與之的整合
6. EntityManager的使用
首先我的開發環境:
jdk1.8+maven3+IDEA

1. 完善pom檔案

<?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>springboot-jpa</groupId> <artifactId>springboot-jpa</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-jpa</name> <description>Demo project for Spring Boot</description
>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>1.4.5.RELEASE</version> <scope>test</scope> </dependency> <!--querydsl依賴--> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <scope>provided</scope> </dependency> <!--阿里巴巴資料庫連線池,專為監控而生 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.26</version> </dependency> <!-- 阿里巴巴fastjson,解析json檢視 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.15</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!--新增QueryDSL外掛支援--> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>

2. 完善application.properties 檔案

spring.datasource.url=jdbc:mysql://localhost:3306/user
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type: com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters:stat
spring.datasource.maxActive: 20
spring.datasource.initialSize: 1
spring.datasource.maxWait: 60000
spring.datasource.minIdle: 1
spring.datasource.timeBetweenEvictionRunsMillis: 60000
spring.datasource.minEvictableIdleTimeMillis: 300000
spring.datasource.validationQuery: select 'x'
spring.datasource.testWhileIdle: true
spring.datasource.testOnBorrow: false
spring.datasource.testOnReturn: false
spring.datasource.poolPreparedStatements: true
spring.datasource.maxOpenPreparedStatements: 20


spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.show-sql=true

3. 編寫實體類 User.java

package com.fantj.model;


import lombok.Data;

import javax.persistence.*;
import java.util.Date;

@Data
@Entity
@Table(name = "user")
public class User {
    public User(){
    }
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(nullable = false)
    private String username;
    @Column(nullable = false)
    private Date birthday;
    @Column(nullable = false)
    private String sex;
    @Column(nullable = false)
    private String address;
}

@Data註解是 lombok 依賴包下的註解,它可以自動幫我們生成set/getter方法,簡化程式碼量。有興趣的可以詳細瞭解,這裡不做多解釋。

4. 實現DAO層

package com.fantj.repostory;

/**
 * Created by Fant.J.
 */
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {

    //自定義repository。手寫sql
    @Query(value = "update user set name=?1 where id=?4",nativeQuery = true)   //佔位符傳值形式
    @Modifying
    int updateById(String name,int id);

    @Query("from User u where u.username=:username")   //SPEL表示式
    User findUser(@Param("username") String username);// 引數username 對映到資料庫欄位username
}

注意:只有@Query 的註解下不能使用insert,我們需要在上面再添加個@Modify註解,我習慣都加,nativeQuery 是詢問是否使用原生sql語句。多表查詢也是在這裡手寫sql,不做演示。因為後面我們用更好的支援多表查詢的工具框架 QueryDSL來幫助我們更簡潔的實現它。

5.實現Service層

UserService .java

package com.fantj.service;

/**
 * Created by Fant.J.
 */
public interface UserService {
    /** 刪除 */
    public void delete(int id);
    /** 增加*/
    public void insert(User user);
    /** 更新*/
    public int update(User user);
    /** 查詢單個*/
    public User selectById(int id);
    /** 查詢全部列表*/
    public Iterator<User> selectAll(int pageNum, int pageSize);
}

UserServiceImpl.java

package com.fantj.service.impl;


/**
 * Created by Fant.J.
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    /**
     * 刪除
     *
     * @param id
     */
    @Override
    public void delete(int id) {
        userRepository.deleteById(id);
    }

    /**
     * 增加
     *
     * @param user
     */
    @Override
    public void insert(User user) {
        userRepository.save(user);
    }

    /**
     * 更新
     *
     * @param user
     */
    @Override
    public int update(User user) {
        userRepository.save(user);
        return 1;
    }

    /**
     * 查詢單個
     *
     * @param id
     */
    @Override
    public User selectById(int id) {
        Optional<User> optional = userRepository.findById(id);
        User user = optional.get();
        return user;
    }

    /**
     * 查詢全部列表,並做分頁
     *  @param pageNum 開始頁數
     * @param pageSize 每頁顯示的資料條數
     */
    @Override
    public Iterator<User> selectAll(int pageNum, int pageSize) {
        //將引數傳給這個方法就可以實現物理分頁了,非常簡單。
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(pageNum, pageSize, sort);
        Page<User> users = userRepository.findAll(pageable);
        Iterator<User> userIterator =  users.iterator();
        return  userIterator;
    }
}

分頁不止可以這樣做,也可以在Controller層進行例項化和初始化然後將Pageable物件傳給Service。
當然也可以對分頁進行封裝,封裝後的展示。

    Page<User> datas = userRepository.findAll(PageableTools.basicPage(1, 5, new SortDto("id")));

是不是很簡潔。大家可以自己嘗試一下。

6. 實現Controller
package com.fantj.controller;

/**
 * Created by Fant.J.
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(method = RequestMethod.GET,value = "/delete/{id}")
    public void delete(@PathVariable("id")int id){
        userService.delete(id);
    }

    @RequestMapping(method = RequestMethod.POST,value = "/insert")
    public void insert(User user){
        userService.insert(user);
    }
    @RequestMapping(method = RequestMethod.POST,value = "/update/{id}")
    public void update(@RequestParam User user){
        userService.update(user);
    }

    @RequestMapping(method = RequestMethod.GET,value = "/{id}/select")
    public User select(@PathVariable("id")int id){
        return userService.selectById(id);
    }

    @RequestMapping(method = RequestMethod.GET,value = "/selectAll/{pageNum}/{pageSize}")
    public List<User> selectAll(@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize){
        Iterator<User> userIterator = userService.selectAll(pageNum, pageSize);
        List<User> list = new ArrayList<>();
        while(userIterator.hasNext()){
            list.add(userIterator.next());
        }
        return list;
    }

}

QueryDSL工具與上文的整合

注意一點,目前springboot2.0 版本對JPA支援有誤,如果你用springboot2 來配置querydsl,application啟動類會執行不起來,正確的依賴包或者是配置類我還沒有找到,希望有點子的朋友可以和我聯絡。 本人QQ:844072586

管理器EntityManager–執行資料庫更新