Springboot整合SpringDataJPA基於Restful風格實現增刪改查功能

前言

本篇文章主要介紹的是Springboot整合SpringDataJPA基於Restful風格實現增刪改查功能。

Spring Boot介紹

Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。通過這種方式,我們不必像Spring MVC一樣寫大量的xml配置文件。

GitHub源碼鏈接位於文章底部。

總結來說,springboot是一個快速開發的框架,開箱即用,提供了各種默認配置來簡化項目配置,能夠集成第三方框架,這是通過maven依賴實現的,它簡化了xml,採用註解的形式,springboot還內嵌了tomcat容器,幫助開發者快速開發與部署。
#####添加依賴
新建一個maven項目,在pom文件中添加以下依賴
這個依賴引入了mvc框架,開啓了接口訪問的方式,它也正是以這種maven依賴的方式集成第三方框架的。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.1.3.RELEASE</version>
    </dependency>
</dependencies>
主程序啓動入口

在controller、service等同級目錄下,創建Application.java啓動類
@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan。
@Configuration負責初始化並啓動spring容器,這個類內部方法上使用@Bean可以實現spring容器的注入。
@EnableAutoConfiguration負責初始化配置,啓動springboot需要啓動的項,後邊詳細解釋此註解的作用。
@ComponentScan負責掃包,springboot啓動程序後,能夠被外部訪問的只有被@SpringBootApplication掃描到的包下的類。
@SpringBootApplication啓動類默認掃包範圍是當前包下或者子包下所有的類。

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
控制層
@RestController
public class HelloWordController {
    @GetMapping("/hello")
    public String index() {
        return "Hello World";
    }
}

成功啓動主程序之後,瀏覽器輸入 http://localhost:8080/hello 便可以查看信息。(因爲沒有配置端口,默認端口就是8080)

修改默認端口

在resource資源目錄下創建application.yml文件

server:
  port: 8081

重新啓動後,瀏覽器輸入 http://localhost:8081/hello 可以查看信息。

application.yml文件內容的格式,以上文中的端口爲例:
server+冒號+空格,然後換行,+一個tab鍵佔位符+port+冒號+空格+8080,
意爲server屬性下的port屬性的值爲8080.

基於Restful風格實現增刪改查功能

一、Restful風格介紹

是一種網絡應用程序的設計風格和開發方式,REST指的是一組架構約束條件和原則。滿足這些約束條件和原則的應用程序或設計就是 RESTful。

每一個URI代表1種資源;
客戶端使用GET、POST、PUT、DELETE4個表示操作方式的動詞對服務端資源進行操作:GET用來獲取資源,POST用來新建資源(也可以用於更新資源),PUT用來更新資源,DELETE用來刪除資源;

二、開發準備

1、新建數據庫和表

在MySql中創建一個名爲springboot的數據庫和名爲一張t_user的表。

CREATE DATABASE `springboot`;

USE `springboot`;

DROP TABLE IF EXISTS `t_user`;

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(10) DEFAULT NULL COMMENT '姓名',
  `age` int(2) DEFAULT NULL COMMENT '年齡',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
2、修改pom文件,添加依賴
    <!--父級依賴,它用來提供相關的 Maven 默認依賴。
    使用它之後,常用的springboot包依賴可以省去version 標籤
    配置UTF-8編碼,指定JDK8-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath ></relativePath>
    </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>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- MySQL 連接驅動依賴 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <!--允許maven創建xml文件,否則xml要放在resources裏-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
3.工程結構

com.lxg.springboot.controller - Controller 層
com.lxg.springboot.dao - 數據操作層 DAO
com.lxg.springboot.common - 存放公共類
com.lxg.springboot.entity - 實體類
com.lxg.springboot.service - 業務邏輯層
Application - 應用啓動類
application.yml - 應用配置文件,應用啓動會自動讀取配置

4.修改application.yml文件,添加數據庫連接屬性
server:
  port: 8080

spring:
  datasource:
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8

三、編碼

1.在common中創建公共類
1.1 封裝分頁結果PageResult
@Data
public class PageResult<T> {
    /**
     * 總記錄數
     */
    private Long total;
    /**
     * 每頁數據
     */
    private List<T> rows;
    public PageResult(Long total, List<T> rows) {
        this.total = total;
        this.rows = rows;
    }
}
1.2 封裝統一返回結果
@Data
public class Result {
    /**
     * 返回結構狀態
     */
    private Boolean flag;

    /**
     * 返回狀態碼
     */
    private Integer code;

    /**
     * 返回消息
     */
    private String message;

    /**
     * 返回數據內容
     */
    private Object data;

    public Result(Boolean flag, Integer code, String message, Object data) {
        this.flag = flag;
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public Result(Boolean flag, Integer code, String message) {
        this.flag = flag;
        this.code = code;
        this.message = message;
    }

    public Result() {
    }
}
1.3 返回狀態碼
public class StatusCode {
    //成功
    public static final Integer OK = 20000;
    //失敗
    public static final Integer ERROR = 20001;
    //用戶名或密碼錯誤
    public static final Integer USER_PASS_ERROR = 20002;
    //權限不足
    public static final Integer ACCESS_ERROR = 20003;
    //遠程調用失敗
    public static final Integer REMOTE_ERROR = 20004;
    //重複操作
    public static final Integer REPEATE_ERROR = 20005;
}
2.在entity中新建實體類
@Data
@Entity
@Table(name="t_user")
public class User implements Serializable {
    /** 編號 */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private String id;
    /** 姓名 */
    private String name;
    /** 年齡 */
    private Integer age;
}

註解:Data:安裝lombok插件再使用該註解可省略getter/setter、無參構造等方法,具體使用見文章https://www.lxgblog.com/article/1572329460
Entity:對實體註釋,聲明實體。
Table:與數據庫表綁定。
Id:聲明Id。
GeneratedValue(strategy = GenerationType.IDENTITY):數據庫主鍵自增。

3.在dao中新建UserDao

UserDao需要繼承JpaRepository<實體類,實體類ID類型>, JpaSpecificationExecutor<實體類>,
JpaRepository<>泛型的第二個參數與id有關,如findById(id)的id類型

public interface UserDao  extends JpaRepository<U實體類ID類型ser,String>, JpaSpecificationExecutor<User> {
	//這裏的數字指的是第幾個參數
    @Modifying
    @Query("update User u set u.age =?2 where u.id =?1")
    void update(String id, Integer age);
}
4.service層新建UserService
@Service
public class UserService {
	@Autowired
	private UserDao userDao;

	/**
	 * 新增或修改,無id爲新增,有id爲修改
	 * @param user
	 */
//	@Transactional
	public void saveUser(User user) {
		userDao.save(user);
		/**
		 * 這裏的save方法會更新所有字段,如果只傳了age屬性進行更新,
		 * name屬性就會修改爲null,避免這個問題需要使用下面的原生Sql
		 * 並且加上方法上的@Transactional註解
		 * userDao.update(user.getId(),user.getAge());
		 */
	}

	/**
	 * 根據id刪除
	 * 
	 * @param id
	 */
	public void deleteUser(String id) {
		userDao.deleteById(id);
	}

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

	/**
	 * 根據id查詢
	 * 
	 * @param id
	 */
	public User findUserById(String id) {
		return userDao.findById(id).get();
	}

    /**
     * 條件查詢+age排序
     * @param searchMap
     */
	public List<User> findSearch(Map searchMap) {
        Specification<User> specification = createSpecification(searchMap);
		Sort sort = new Sort(Sort.Direction.ASC, "age");
        return userDao.findAll(specification,sort);
	}

    /**
     * 條件+分頁+age排序
     * @param searchMap
     * @param page
     * @param size
     */
	public Page<User> findSearch(Map searchMap, int page, int size) {
		Specification<User> specification = createSpecification(searchMap);
		Sort sort = new Sort(Sort.Direction.ASC, "age");
		PageRequest pageRequest = PageRequest.of(page - 1, size,sort);
		return userDao.findAll(specification, pageRequest);
	}

	/**
	 * 創建查詢條件
	 */
	private Specification<User> createSpecification(Map searchMap) {
		return new Specification<User>() {
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery,
					CriteriaBuilder criteriaBuilder) {
				List<Predicate> preList = new ArrayList<Predicate>();
				if (searchMap.get("name") != null && !(searchMap.get("name")).equals("")) {
					preList.add(
							criteriaBuilder.like(root.get("name").as(String.class), "%" + searchMap.get("name") + "%"));
				}
				if (searchMap.get("age") != null && !(searchMap.get("age")).equals("")) {
					preList.add(criteriaBuilder.equal(root.get("age").as(Integer.class), searchMap.get("age")));
				}
				Predicate[] preArray = new Predicate[preList.size()];
				return criteriaBuilder.and(preList.toArray(preArray));
			}
		};
	}
}
5.controller層
@RestController
@RequestMapping(value = "/user")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 新增
     * @param user
     */
    @RequestMapping(method = RequestMethod.POST)
    public Result addUser(@RequestBody User user) {
        userService.saveUser(user);
        return new Result(true, StatusCode.OK,"新增成功");
    }

    /**
     * 修改
     * @param user
     */
    @RequestMapping(method = RequestMethod.PUT)
    public Result updateUser(@RequestBody User user) {
        if (user.getId() == null || user.getId().equals("")) {
            return new Result(false, StatusCode.ERROR,"無id,更新失敗");
        }
        userService.saveUser(user);
        return new Result(true, StatusCode.OK,"更新成功");
    }

    /**
     * 根據id刪除
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Result delete(@PathVariable String id) {
        userService.deleteUser(id);
        return new Result(true, StatusCode.OK,"刪除成功");
    }

    /**
     * 查詢所有
     */
    @RequestMapping(method = RequestMethod.GET)
    public List<User> findAllUser() {
        return userService.findAll();
    }

    /**
     * 根據id查詢
     * @param id
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Result findByUserId(@PathVariable String id) {
        return new Result(true, StatusCode.OK,"查詢成功",userService.findUserById(id));
    }

    /**
     * 條件查詢
     */
    @RequestMapping(value="/search",method = RequestMethod.POST)
    public Result findSearch(@RequestBody Map searchMap){
        return new Result(true,StatusCode.OK,"查詢成功 ",userService.findSearch(searchMap));
    }

    /**
     * 條件+分頁
     * @param searchMap
     * @param page
     * @param size
     */
    @RequestMapping(value = "/search/{page}/{size}",method = RequestMethod.POST)
    public Result findSearch(@RequestBody Map searchMap,@PathVariable int page,@PathVariable int size){
        Page<User> pageBean = userService.findSearch(searchMap, page, size);
        return new Result(true,StatusCode.OK,"查詢成功",new PageResult<>(pageBean.getTotalElements(),pageBean.getContent()) );
    }
}

@PathVariable註解的參數與@RequestMapping中value中的{}內參數一致。

四、測試

啓動Application 之後,使用postman工具進行接口的測試。postman的使用教程查看另一偏博文。

1.新增

2.根據id屬性刪除,再次查詢所有,會發現少了一條

3.根據id屬性修改,再次查詢所有,會發現已經改變。

4.查詢所有

5.根據id屬性查詢

6.條件+age排序查詢

6.條件+age排序+分頁查詢


經過上面的例子可以發現,增刪改查的url都是同一個,即localhost:8080/user, 如果有一些簡單的條件,則放到它的後面作爲條件。作爲區別,使用了不同的請求方式,如Post,Get,Put,Delete等。

本文GitHub源碼:https://github.com/lixianguo5097/springboot/tree/master/springboot-jpa

CSDN:https://blog.csdn.net/qq_27682773
簡書:https://www.jianshu.com/u/e99381e6886e
博客園:https://www.cnblogs.com/lixianguo
個人博客:https://www.lxgblog.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章