Spring Data JPA -- 環境搭建

1.新建SpringBoot項目,在 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.chen</groupId>
    <artifactId>chen</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>chen</name>
    <description>Demo project for Spring Boot</description>

    <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-web</artifactId>
        </dependency>

        <!--導入jpa依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--MySQL驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- lombok簡化實體類代碼 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.新建項目架構

3.在 application.properties 進行配置

server.port=80

#數據庫配置
spring.datasource.url=jdbc:mysql://localhost:3306/chen?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456

# 參數說明 create-運行項目時創建表,update-運行項目時更新表,none-不做操作
spring.jpa.hibernate.ddl-auto=none
# 打印sql語句
spring.jpa.show-sql=true

5.利用aop進行全局異常處理

package com.chen.aop;

import com.chen.domain.AppConstant;
import com.chen.restful.RestResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

/**
 * 全局異常處理類
 *
 * @author chen
 */
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    private static final String logExceptionFormat = "服務器異常: Code: %s Detail: %s";
    private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    //運行時異常
    @ExceptionHandler(RuntimeException.class)
    public RestResponse runtimeExceptionHandler(RuntimeException ex) {
        System.err.println("RuntimeException:");
        return resultOut(AppConstant.RunTime, "服務器內部錯誤,運行異常", ex);
    }

    //空指針異常
    @ExceptionHandler(NullPointerException.class)
    public RestResponse nullPointerExceptionHandler(NullPointerException ex) {
        System.err.println("NullPointerException:");
        return resultOut(AppConstant.NullPointer, "空指針異常", ex);
    }

    //類型轉換異常
    @ExceptionHandler(ClassCastException.class)
    public RestResponse classCastExceptionHandler(ClassCastException ex) {
        System.err.println("ClassCastException:");
        return resultOut(AppConstant.ClassCast, "類型轉換異常", ex);
    }

    //IO異常
    @ExceptionHandler(IOException.class)
    public RestResponse iOExceptionHandler(IOException ex) {
        System.err.println("IOException:");
        return resultOut(AppConstant.IO, "IO異常", ex);
    }

    //未知方法異常
    @ExceptionHandler(NoSuchMethodException.class)
    public RestResponse noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        System.err.println("NoSuchMethodException:");
        return resultOut(AppConstant.NoSuchMethod, "未知方法異常", ex);
    }

    //數組越界異常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public RestResponse indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        System.err.println("IndexOutOfBoundsException:");
        return resultOut(AppConstant.IndexOutOfBounds, "數組越界異常", ex);
    }

    //400錯誤
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public RestResponse requestNotReadable(HttpMessageNotReadableException ex) {
        System.err.println("HttpMessageNotReadableException");
        return resultOut(AppConstant.HttpMessageNotReadable, "400 bad request", ex);
    }

    //400錯誤
    @ExceptionHandler({TypeMismatchException.class})
    public RestResponse requestTypeMismatch(TypeMismatchException ex) {
        System.err.println("TypeMismatchException:");
        return resultOut(AppConstant.TypeMismatch, "400 bad request", ex);
    }

    //400錯誤
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public RestResponse requestMissingServletRequest(MissingServletRequestParameterException ex) {
        System.err.println("MissingServletRequestParameterException:");
        return resultOut(AppConstant.MissingServletRequestParameter, "400 bad request", ex);
    }

    //405錯誤
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public RestResponse request405(HttpRequestMethodNotSupportedException ex) {
        System.err.println("HttpRequestMethodNotSupportedException:");
        return resultOut(AppConstant.HttpRequestMethodNotSupported, "405 Method not allowed", ex);
    }

    //406錯誤
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public RestResponse request406(HttpMediaTypeNotAcceptableException ex) {
        System.err.println("HttpMediaTypeNotAcceptableException:");
        return resultOut(AppConstant.HttpMediaTypeNotAcceptable, "406 Not Acceptable", ex);
    }

    //500錯誤
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public RestResponse server500(RuntimeException ex) {
        System.err.println("RuntimeException:");
        return resultOut(AppConstant.HttpMediaTypeNotAcceptable, "500 error", ex);
    }

    //棧溢出
    @ExceptionHandler({StackOverflowError.class})
    public RestResponse requestStackOverflow(StackOverflowError ex) {
        System.err.println("StackOverflowError:");
        return resultOut(AppConstant.StackOverflow, "棧溢出異常", ex);
    }

    //除數不能爲0
    @ExceptionHandler({ArithmeticException.class})
    public RestResponse arithmeticException(ArithmeticException ex) {
        System.err.println("ArithmeticException:");
        return resultOut(AppConstant.Arithmetic, "除數不能爲0", ex);
    }

    //其他錯誤
    @ExceptionHandler({Exception.class})
    public RestResponse exception(Exception ex) {
        System.err.println("Exception:");
        return resultOut(AppConstant.other, "其他異常", ex);
    }

    /**
     * 對返回數據集中處理
     *
     * @param code
     * @param msg
     * @param ex
     * @param <T>
     * @return
     */
    private <T extends Throwable> RestResponse resultOut(int code, String msg, T ex) {
        ex.printStackTrace();
        log.error(String.format(logExceptionFormat, code, ex.getMessage()));
        return RestResponse.fail(code).msg(msg);
    }

}

6.封裝常量類

package com.chen.domain;

/**
 * 對常量進行封裝,利於後期代碼的維護
 *
 * @author chen
 */
public class AppConstant {

    // 文本消息
    public static final String MESSAGE = "message";

    // 單個對象
    public static final String ITEM = "item";

    // 返回的對象列表
    public static final String LIST = "list";

    // 狀態碼
    public static final String CODE = "code";

    // 代表執行成功
    public static int OK = 0;

    // 代表執行失敗
    public static int FAIL = 1;

    // 代表服務器運行異常
    public static int RunTime = 2;

    // 代表空指針異常
    public static int NullPointer = 3;

    // 類型轉換異常
    public static int ClassCast = 4;

    // IO異常
    public static int IO = 5;

    // 未知方法異常
    public static int NoSuchMethod = 6;

    // 數組越界異常
    public static int IndexOutOfBounds = 7;

    // 400錯誤
    public static int HttpMessageNotReadable=8;

    // 400錯誤
    public static int TypeMismatch=9;

    // 400錯誤
    public static int MissingServletRequestParameter=10;

    // 405錯誤
    public static int HttpRequestMethodNotSupported=11;

    // 406錯誤
    public static int HttpMediaTypeNotAcceptable=12;

    // 500錯誤
    public static int Run500=13;

    // 棧溢出
    public static int StackOverflow=14;

    // 除數爲0異常
    public static int Arithmetic=15;

    // 其他異常
    public static int other=16;

}

7.封裝rest數據

package com.chen.restful;

import com.chen.domain.AppConstant;

import java.util.HashMap;
import java.util.List;

/**
 * REST 接口返回數據
 *
 * @author chen
 */
public class RestResponse extends HashMap<String, Object> {

    /**
     * 禁止通過構造函數構造對象,只能通過靜態方法獲取實例。
     *
     * @see #ok()
     * @see #ok(String)
     * @see #fail()
     * @see #fail(String)
     */
    private RestResponse() {
    }

    /**
     * 設置接口返回的文本消息,屬性 key: message
     *
     * @param msg
     * @return
     */
    public RestResponse msg(String msg) {
        this.put(AppConstant.MESSAGE, msg);
        return this;
    }

    /**
     * 設置接口返回的數據對象,屬性 key: item
     *
     * @param item
     * @return
     */
    public RestResponse item(Object item) {
        this.put(AppConstant.ITEM, item);
        return this;
    }

    /**
     * 設置接口返回的數據對象列表,屬性 key: list
     *
     * @param list
     * @return
     */
    public RestResponse list(List<?> list) {
        this.put(AppConstant.LIST, list);
        return this;
    }

    /**
     * 設置接口返回的數據項,並指定數據項的屬性 key
     *
     * @param key
     * @param value
     * @return
     */
    public RestResponse put(String key, Object value) {
        super.put(key, value);
        return this;
    }

    /**
     * 接口執行成功的返回數據,其中屬性 CODE = 0
     *
     * @return
     */
    public static RestResponse ok() {
        RestResponse result = new RestResponse();
        result.put(AppConstant.CODE, AppConstant.OK);
        return result;
    }

    /**
     * 接口執行成功的返回數據,並設置文本消息
     *
     * @param msg
     * @return
     */
    public static RestResponse ok(String msg) {
        RestResponse result = new RestResponse();
        result.put(AppConstant.CODE, AppConstant.OK).msg(msg);
        return result;
    }

    /**
     * 接口執行成功的返回數據,並設置對象數據
     *
     * @param item
     * @return
     */
    public static RestResponse ok(Object item) {
        RestResponse result = new RestResponse();
        result.put(AppConstant.CODE, AppConstant.OK).item(item);
        return result;
    }

    /**
     * 接口執行成功的返回數據,並設置列表對象數據
     *
     * @param list
     * @return
     */
    public static RestResponse ok(List<?> list) {
        RestResponse result = new RestResponse();
        result.put(AppConstant.CODE, AppConstant.OK).list(list);
        return result;
    }

    /**
     * 接口執行失敗的返回數據,其中屬性 CODE = 1
     *
     * @return
     */
    public static RestResponse fail() {
        RestResponse result = new RestResponse();
        result.put(AppConstant.CODE, AppConstant.FAIL);
        return result;
    }

    /**
     * 接口執行失敗的返回數據,並設置文本消息,其中屬性 CODE = 1, message = {msg}
     *
     * @param msg
     * @return
     */
    public static RestResponse fail(String msg) {
        RestResponse result = new RestResponse();
        result.put(AppConstant.CODE, AppConstant.FAIL).msg(msg);
        return result;
    }

    /**
     * 接口執行失敗的返回數據,自定義狀態碼,其中屬性 CODE = {errcode}
     *
     * @param errcode
     * @return
     */
    public static RestResponse fail(int errcode) {
        RestResponse result = new RestResponse();
        result.put(AppConstant.CODE, errcode);
        return result;
    }
}

8.編寫測試實體類

package com.chen.domain.entity;

import lombok.Data;

import javax.persistence.*;

@Data
@Entity
@Table(name = "test_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long userId;

    @Column(name = "user_name")
    private String userName;

    @Column(name = "age")
    private Integer age;

}

註解說明:

@Entity //聲明實體類

@Table(name="") //建立實體類和表的映射關係

@Id//聲明當前私有屬性爲主鍵

@GeneratedValue(strategy=GenerationType.IDENTITY) //配置主鍵的生成策略

@Column(name="") //指定和表中字段的映射關係

9.編寫dao層接口,需要繼承 JpaRepository 

package com.chen.dao;


import com.chen.domain.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

@Repository
public interface UserDao extends JpaRepository<User,Long>, JpaSpecificationExecutor<User> {

}

說明:利用JPA規範,實現不用編寫數據庫代碼進行簡單的數據庫單表操作

10.編寫service業務層,調用dao層接口

package com.chen.service;

import com.chen.dao.UserDao;
import com.chen.domain.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;

@Service
@Transactional
public class UserService {

    @Autowired
    private UserDao userDao;

    /**
     * 查詢所有數據
     * @return
     */
    public List<User> findAll(){
       return userDao.findAll();
    }

}

11.實現controller接口調用層

package com.chen.controller;

import com.chen.domain.entity.User;
import com.chen.restful.RestResponse;
import com.chen.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 查詢所有用戶
     * @return
     */
    @RequestMapping("findAll")
    public RestResponse findAll(){
        List<User> all = userService.findAll();
        return RestResponse.ok().msg("處理成功").item(all);
    }

}

12.配置啓動類

package com.chen;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EntityScan(basePackages = "com.chen.domain.entity")
@EnableJpaRepositories(basePackages = "com.chen.dao")
public class ChenApplication {

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

}

13.測試

發佈了135 篇原創文章 · 獲贊 76 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章