Springboot整合SpringDataJPA基于Restful風(fēng)格實(shí)現(xiàn)增刪改查功能

前言

本篇文章主要介紹的是Springboot整合SpringDataJPA基于Restful風(fēng)格實(shí)現(xiàn)增刪改查功能王凑。

Spring Boot介紹

Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架盈匾,其設(shè)計(jì)目的是用來簡化新Spring應(yīng)用的初始搭建以及開發(fā)過程悼尾。該框架使用了特定的方式來進(jìn)行配置,從而使開發(fā)人員不再需要定義樣板化的配置蟀架。通過這種方式寝蹈,我們不必像Spring MVC一樣寫大量的xml配置文件。

GitHub源碼鏈接位于文章底部侄非。

總結(jié)來說蕉汪,springboot是一個(gè)快速開發(fā)的框架,開箱即用逞怨,提供了各種默認(rèn)配置來簡化項(xiàng)目配置者疤,能夠集成第三方框架,這是通過maven依賴實(shí)現(xiàn)的叠赦,它簡化了xml驹马,采用注解的形式,springboot還內(nèi)嵌了tomcat容器除秀,幫助開發(fā)者快速開發(fā)與部署糯累。

添加依賴

新建一個(gè)maven項(xiàng)目,在pom文件中添加以下依賴
這個(gè)依賴引入了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等同級目錄下仗岸,創(chuàng)建Application.java啟動類
SpringBootApplication注解=Configuration注解+EnableAutoConfiguration注解+ComponentScan注解允耿。
Configuration注解負(fù)責(zé)初始化并啟動spring容器,這個(gè)類內(nèi)部方法上使用Bean注解可以實(shí)現(xiàn)spring容器的注入扒怖。
EnableAutoConfiguration注解負(fù)責(zé)初始化配置较锡,啟動springboot需要啟動的項(xiàng),后邊詳細(xì)解釋此注解的作用盗痒。
ComponentScan注解負(fù)責(zé)掃包蚂蕴,springboot啟動程序后,能夠被外部訪問的只有被SpringBootApplication注解掃描到的包下的類俯邓。
SpringBootApplication注解啟動類默認(rèn)掃包范圍是當(dāng)前包下或者子包下所有的類骡楼。

@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 便可以查看信息稽鞭。(因?yàn)闆]有配置端口鸟整,默認(rèn)端口就是8080)

修改默認(rèn)端口

在resource資源目錄下創(chuàng)建application.yml文件

server:
  port: 8081

重新啟動后,瀏覽器輸入 http://localhost:8081/hello 可以查看信息朦蕴。

application.yml文件內(nèi)容的格式篮条,以上文中的端口為例:
server+冒號+空格,然后換行吩抓,+一個(gè)tab鍵占位符+port+冒號+空格+8080涉茧,
意為server屬性下的port屬性的值為8080.

基于Restful風(fēng)格實(shí)現(xiàn)增刪改查功能

一、Restful風(fēng)格介紹

是一種網(wǎng)絡(luò)應(yīng)用程序的設(shè)計(jì)風(fēng)格和開發(fā)方式疹娶,REST指的是一組架構(gòu)約束條件和原則伴栓。滿足這些約束條件和原則的應(yīng)用程序或設(shè)計(jì)就是 RESTful。

每一個(gè)URI代表1種資源雨饺;
客戶端使用GET钳垮、POST、PUT额港、DELETE4個(gè)表示操作方式的動詞對服務(wù)端資源進(jìn)行操作:GET用來獲取資源饺窿,POST用來新建資源(也可以用于更新資源),PUT用來更新資源锹安,DELETE用來刪除資源短荐;

二、開發(fā)準(zhǔn)備

1叹哭、新建數(shù)據(jù)庫和表

在MySql中創(chuàng)建一個(gè)名為springboot的數(shù)據(jù)庫和名為一張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文件风罩,添加依賴
    <!--父級依賴糠排,它用來提供相關(guān)的 Maven 默認(rèn)依賴。
    使用它之后超升,常用的springboot包依賴可以省去version 標(biāo)簽
    配置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 連接驅(qū)動依賴 -->
        <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創(chuàng)建xml文件哺徊,否則xml要放在resources里-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
3.工程結(jié)構(gòu)

com.lxg.springboot.controller - Controller 層
com.lxg.springboot.dao - 數(shù)據(jù)操作層 DAO
com.lxg.springboot.common - 存放公共類
com.lxg.springboot.entity - 實(shí)體類
com.lxg.springboot.service - 業(yè)務(wù)邏輯層
Application - 應(yīng)用啟動類
application.yml - 應(yīng)用配置文件,應(yīng)用啟動會自動讀取配置


image
4.修改application.yml文件乾闰,添加數(shù)據(jù)庫連接屬性
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中創(chuàng)建公共類
1.1 封裝分頁結(jié)果PageResult
@Data
public class PageResult<T> {
    /**
     * 總記錄數(shù)
     */
    private Long total;
    /**
     * 每頁數(shù)據(jù)
     */
    private List<T> rows;
    public PageResult(Long total, List<T> rows) {
        this.total = total;
        this.rows = rows;
    }
}
1.2 封裝統(tǒng)一返回結(jié)果
@Data
public class Result {
    /**
     * 返回結(jié)構(gòu)狀態(tài)
     */
    private Boolean flag;

    /**
     * 返回狀態(tài)碼
     */
    private Integer code;

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

    /**
     * 返回?cái)?shù)據(jù)內(nèi)容
     */
    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 返回狀態(tài)碼
public class StatusCode {
    //成功
    public static final Integer OK = 20000;
    //失敗
    public static final Integer ERROR = 20001;
    //用戶名或密碼錯(cuò)誤
    public static final Integer USER_PASS_ERROR = 20002;
    //權(quán)限不足
    public static final Integer ACCESS_ERROR = 20003;
    //遠(yuǎn)程調(diào)用失敗
    public static final Integer REMOTE_ERROR = 20004;
    //重復(fù)操作
    public static final Integer REPEATE_ERROR = 20005;
}
2.在entity中新建實(shí)體類
@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、無參構(gòu)造等方法涯肩,具體使用見文章https://www.lxgblog.com/article/1572329460
Entity:對實(shí)體注釋轿钠,聲明實(shí)體。
Table:與數(shù)據(jù)庫表綁定病苗。
Id:聲明Id疗垛。
GeneratedValue(strategy = GenerationType.IDENTITY):數(shù)據(jù)庫主鍵自增。

3.在dao中新建UserDao

UserDao需要繼承JpaRepository<實(shí)體類,實(shí)體類ID類型>, JpaSpecificationExecutor<實(shí)體類>硫朦,
JpaRepository<>泛型的第二個(gè)參數(shù)與id有關(guān)贷腕,如findById(id)的id類型

public interface UserDao  extends JpaRepository<U實(shí)體類ID類型ser,String>, JpaSpecificationExecutor<User> {
    //這里的數(shù)字指的是第幾個(gè)參數(shù)
    @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屬性進(jìn)行更新,
         * name屬性就會修改為null挚赊,避免這個(gè)問題需要使用下面的原生Sql
         * 并且加上方法上的@Transactional注解
         * userDao.update(user.getId(),user.getAge());
         */
    }

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

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

    /**
     * 根據(jù)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);
    }

    /**
     * 創(chuàng)建查詢條件
     */
    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,"更新成功");
    }

    /**
     * 根據(jù)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();
    }

    /**
     * 根據(jù)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注解的參數(shù)與@RequestMapping中value中的{}內(nèi)參數(shù)一致诡壁。

四济瓢、測試

啟動Application 之后荠割,使用postman工具進(jìn)行接口的測試。postman的使用教程查看另一偏博文旺矾。

1.新增
image
2.根據(jù)id屬性刪除蔑鹦,再次查詢所有,會發(fā)現(xiàn)少了一條
image
3.根據(jù)id屬性修改箕宙,再次查詢所有嚎朽,會發(fā)現(xiàn)已經(jīng)改變。
image
4.查詢所有
image
5.根據(jù)id屬性查詢
image
6.條件+age排序查詢
image
6.條件+age排序+分頁查詢
image

經(jīng)過上面的例子可以發(fā)現(xiàn)柬帕,增刪改查的url都是同一個(gè),即localhost:8080/user, 如果有一些簡單的條件哟忍,則放到它的后面作為條件。作為區(qū)別陷寝,使用了不同的請求方式,如Post,Get,Put,Delete等。

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

CSDN:https://blog.csdn.net/qq_27682773
簡書:http://www.reibang.com/u/e99381e6886e
博客園:https://www.cnblogs.com/lixianguo
個(gè)人博客:https://www.lxgblog.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末剧蹂,一起剝皮案震驚了整個(gè)濱河市氢烘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌仔引,老刑警劉巖扔仓,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褐奥,死亡現(xiàn)場離奇詭異,居然都是意外死亡翘簇,警方通過查閱死者的電腦和手機(jī)撬码,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來版保,“玉大人耍群,你說我怎么就攤上這事≌殷荩” “怎么了蹈垢?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長袖裕。 經(jīng)常有香客問我曹抬,道長,這世上最難降的妖魔是什么急鳄? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任谤民,我火速辦了婚禮,結(jié)果婚禮上疾宏,老公的妹妹穿的比我還像新娘张足。我一直安慰自己,他們只是感情好坎藐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布为牍。 她就那樣靜靜地躺著,像睡著了一般岩馍。 火紅的嫁衣襯著肌膚如雪碉咆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天蛀恩,我揣著相機(jī)與錄音疫铜,去河邊找鬼。 笑死双谆,一個(gè)胖子當(dāng)著我的面吹牛壳咕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播顽馋,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼谓厘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了趣避?” 一聲冷哼從身側(cè)響起庞呕,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后住练,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體地啰,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年讲逛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亏吝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盏混,死狀恐怖蔚鸥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情许赃,我是刑警寧澤止喷,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站混聊,受9級特大地震影響弹谁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜句喜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一预愤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咳胃,春花似錦植康、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至标沪,卻和暖如春榄攀,著一層夾襖步出監(jiān)牢的瞬間嗜傅,已是汗流浹背金句。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吕嘀,地道東北人违寞。 一個(gè)月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像偶房,于是被迫代替她去往敵國和親趁曼。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容