• 玩转spring boot——结合JPA入门


    参考官方例子:https://spring.io/guides/gs/accessing-data-jpa/

    接着上篇内容

    一、小试牛刀


    创建maven项目后,修改pom.xml文件

    <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>com.github.carter659</groupId>
        <artifactId>spring05</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.4.2.RELEASE</version>
        </parent>
    
        <name>spring05</name>
        <url>http://maven.apache.org</url>
    
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
        </properties>
    
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>commons-dbcp</groupId>
                <artifactId>commons-dbcp</artifactId>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    pom.xml

    多引入了JPA的依赖:

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    src/main/resources/application.properties和src/main/resources/templates/index.html保持上篇不变:

    spring.datasource.initialize=false
    spring.datasource.url=jdbc:mysql://localhost:3306/demo
    spring.datasource.username=root
    spring.datasource.password=
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    application.properties
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>玩转spring boot——结合JPA</title>
    <script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
    <script type="text/javascript">
        /*<![CDATA[*/
        var app = angular.module('app', []);
        app.controller('MainController', function($rootScope, $scope, $http) {
    
            $scope.data = {};
            $scope.rows = [];
    
            //添加
            $scope.add = function() {
                $scope.data = {
                    no : 'No.1234567890',
                    quantity : 100,
                    'date' : '2016-12-30'
                };
            }
    
            //编辑
            $scope.edit = function(id) {
                for ( var i in $scope.rows) {
                    var row = $scope.rows[i];
                    if (id == row.id) {
                        $scope.data = row;
                        return;
                    }
                }
            }
    
            //移除
            $scope.remove = function(id) {
                for ( var i in $scope.rows) {
                    var row = $scope.rows[i];
                    if (id == row.id) {
                        $scope.rows.splice(i, 1);
                        return;
                    }
                }
            }
    
            //保存
            $scope.save = function() {
                $http({
                    url : '/save',
                    method : 'POST',
                    data : $scope.data
                }).success(function(r) {
                    //保存成功后更新数据
                    $scope.get(r.id);
                });
            }
    
            //删除
            $scope.del = function(id) {
                $http({
                    url : '/delete?id=' + id,
                    method : 'POST',
                }).success(function(r) {
                    //删除成功后移除数据
                    $scope.remove(r.id);
                });
            }
    
            //获取数据
            $scope.get = function(id) {
                $http({
                    url : '/get?id=' + id,
                    method : 'POST',
                }).success(function(data) {
                    for ( var i in $scope.rows) {
                        var row = $scope.rows[i];
                        if (data.id == row.id) {
                            row.no = data.no;
                            row.date = data.date;
                            row.quantity = data.quantity;
                            return;
                        }
                    }
                    $scope.rows.push(data);
                });
            }
    
            //初始化载入数据
            $http({
                url : '/findAll',
                method : 'POST'
            }).success(function(rows) {
                for ( var i in rows) {
                    var row = rows[i];
                    $scope.rows.push(row);
                }
            });
        });
        /*]]>*/
    </script>
    </head>
    <body ng-app="app" ng-controller="MainController">
        <h1>玩转spring boot——结合JPA</h1>
        <h4>
            <a href="http://www.cnblogs.com/GoodHelper/">from 刘冬的博客</a>
        </h4>
        <input type="button" value="添加" ng-click="add()" />
        <input type="button" value="保存" ng-click="save()" />
        <br />
        <br />
        <h3>清单信息:</h3>
        <input id="id" type="hidden" ng-model="data.id" />
        <table cellspacing="1" style="background-color: #a0c6e5">
            <tr>
                <td>编号:</td>
                <td><input id="no" ng-model="data.no" /></td>
                <td>日期:</td>
                <td><input id="date" ng-model="data.date" /></td>
                <td>数量:</td>
                <td><input id="quantity" ng-model="data.quantity" /></td>
            </tr>
        </table>
    
        <br />
        <h3>清单列表:</h3>
        <table cellspacing="1" style="background-color: #a0c6e5">
            <tr
                style="text-align: center; COLOR: #0076C8; BACKGROUND-COLOR: #F4FAFF; font-weight: bold">
                <td>操作</td>
                <td>编号</td>
                <td>日期</td>
                <td>数量</td>
            </tr>
            <tr ng-repeat="row in rows" bgcolor='#F4FAFF'>
                <td><input ng-click="edit(row.id)" value="编辑" type="button" /><input
                    ng-click="del(row.id)" value="删除" type="button" /></td>
                <td>{{row.no}}</td>
                <td>{{row.date}}</td>
                <td>{{row.quantity}}</td>
            </tr>
        </table>
    
        <br />
        <a href="http://www.cnblogs.com/GoodHelper/">点击访问原版博客</a>
    </body>
    </html>
    index.html

    修改上篇的“Order.java”类:

    package com.github.carter659.spring05;
    
    import java.util.Date;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    import org.hibernate.annotations.GenericGenerator;
    
    /**
     * 博客出处:http://www.cnblogs.com/GoodHelper/
     * 
     * @author 刘冬
     *
     */
    @Entity
    @Table(name = "t_order")
    public class Order {
    
        @Id
        @GeneratedValue(generator = "uuid")
        @GenericGenerator(name = "uuid", strategy = "uuid2")
        @Column(name = "order_id", length = 36)
        public String id;
    
        @Column(name = "order_no", length = 50)
        public String no;
    
        @Temporal(TemporalType.DATE)
        @Column(name = "order_date")
        public Date date;
    
        @Column(name = "quantity")
        public int quantity;
    
        /**
         * 省略 get set
         */
    }

    新建“OrderRepository.java”文件

    package com.github.carter659.spring05;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    /**
     * 博客出处:http://www.cnblogs.com/GoodHelper/
     * 
     * @author 刘冬
     *
     */
    public interface OrderRepository extends JpaRepository<Order, String> {
    
        
    }

    这个类实现了JpaRepository<>接口,此接口附带常用的增删改查到方法。

    修改上篇的控制器“MainController.java”文件

    package com.github.carter659.spring05;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * 博客出处:http://www.cnblogs.com/GoodHelper/
     * 
     * @author 刘冬
     *
     */
    @Controller
    public class MainController {
    
        @Autowired
        private OrderRepository orderRepository;
    
        @GetMapping("/")
        public String index() {
            return "index";
        }
    
        /**
         * 持久化
         * 
         * @param entity
         * @return
         */
        @PostMapping("/save")
        public @ResponseBody Map<String, Object> save(@RequestBody Order entity) {
            Map<String, Object> result = new HashMap<>();
            entity = orderRepository.save(entity);
            result.put("id", entity.id);
            return result;
        }
    
        /**
         * 获取对象
         * 
         * @param id
         * @return
         */
        @PostMapping("/get")
        public @ResponseBody Object get(String id) {
            return orderRepository.findOne(id);
        }
    
        /**
         * 获取全部
         * 
         * @return
         */
        @PostMapping("/findAll")
        public @ResponseBody Object findAll() {
            return orderRepository.findAll();
        }
    
        /**
         * 删除
         * 
         * @param id
         * @return
         */
        @PostMapping("/delete")
        public @ResponseBody Map<String, Object> delete(String id) {
            Map<String, Object> result = new HashMap<>();
            orderRepository.delete(id);
            result.put("id", id);
            return result;
        }
    }

    有人会问,在控制器中直接依赖注入了OrderRepository,并没有OrderRepository接口的实现类。在没有写实现类的情况下不报错吗?答案是并不报错,因为这些事儿都交给了JPA去做。那么为什么要用JPA,答案也只有2个字“方便”。我写这个系列博客的目的就是为了体现“方便”二字,使用最方便的技术来快速开发项目。

    言归正传,App.java类保持不变:

    package com.github.carter659.spring05;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * 博客出处:http://www.cnblogs.com/GoodHelper/
     * 
     * @author 刘冬
     *
     */
    @SpringBootApplication
    public class App {
    
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    }
    App.java

    完整的项目结构如下图所示:

    运行效果如下图,我就不做说明了:

    二、高级查询


     修改“OrderRepository.java”:

    package com.github.carter659.spring05;
    
    import java.util.Date;
    import java.util.List;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    /**
     * 博客出处:http://www.cnblogs.com/GoodHelper/
     * 
     * @author 刘冬
     *
     */
    public interface OrderRepository extends JpaRepository<Order, String> {
    
        /**
         * like查询
         * 
         * @param no
         * @return
         */
        List<Order> findAllByNoLike(String no);
    
        /**
         * between查询
         * 
         * @param startDate
         * @param endDate
         * @return
         */
        List<Order> findAllByDateBetween(Date startDate, Date endDate);
    
        /**
         * 小于查询
         * 
         * @param quantity
         * @return
         */
        List<Order> findAllByQuantityLessThan(int quantity);
    }
    package com.github.carter659.spring05;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.propertyeditors.CustomDateEditor;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.WebDataBinder;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.InitBinder;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * 博客出处:http://www.cnblogs.com/GoodHelper/
     * 
     * @author 刘冬
     *
     */
    @Controller
    public class MainController {
    
        @Autowired
        private OrderRepository orderRepository;
    
        /**
         * 处理日期类型
         * 
         * @param binder
         */
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            dateFormat.setLenient(false);
            binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        }
    
        @GetMapping("/")
        public String index() {
            return "index";
        }
    
        /**
         * 持久化
         * 
         * @param entity
         * @return
         */
        @PostMapping("/save")
        public @ResponseBody Map<String, Object> save(@RequestBody Order entity) {
            Map<String, Object> result = new HashMap<>();
            entity = orderRepository.save(entity);
            result.put("id", entity.id);
            return result;
        }
    
        /**
         * 获取对象
         * 
         * @param id
         * @return
         */
        @PostMapping("/get")
        public @ResponseBody Object get(String id) {
            return orderRepository.findOne(id);
        }
    
        /**
         * 获取全部
         * 
         * @return
         */
        @PostMapping("/findAll")
        public @ResponseBody Object findAll() {
            return orderRepository.findAll();
        }
    
        /**
         * 删除
         * 
         * @param id
         * @return
         */
        @PostMapping("/delete")
        public @ResponseBody Map<String, Object> delete(String id) {
            Map<String, Object> result = new HashMap<>();
            orderRepository.delete(id);
            result.put("id", id);
            return result;
        }
    
        /**
         * like查询
         * 
         * @return
         */
        @PostMapping("/findAllByNoLike")
        public @ResponseBody Object findAllByNoLike(@RequestParam String no) {
            return orderRepository.findAllByNoLike("%" + no + "%");
        }
    
        /**
         * between查询
         * 
         * @return
         */
        @PostMapping("/findAllByDateBetween")
        public @ResponseBody Object findAllByDateBetween(@RequestParam Date startDate, @RequestParam Date endDate) {
            return orderRepository.findAllByDateBetween(startDate, endDate);
        }
    
        /**
         * 小于查询
         * 
         * @return
         */
        @PostMapping("/findAllByQuantityLessThan")
        public @ResponseBody Object findAllByQuantityLessThan(int quantity) {
            return orderRepository.findAllByQuantityLessThan(quantity);
        }
    }
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>玩转spring boot——结合JPA</title>
    <script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
    <script type="text/javascript">
        /*<![CDATA[*/
        var app = angular.module('app', []);
        app
                .controller(
                        'MainController',
                        function($rootScope, $scope, $http) {
    
                            $scope.data = {};
                            $scope.rows = [];
    
                            //添加
                            $scope.add = function() {
                                $scope.data = {
                                    no : 'No.1234567890',
                                    quantity : 100,
                                    'date' : '2016-12-30'
                                };
                            }
    
                            //编辑
                            $scope.edit = function(id) {
                                for ( var i in $scope.rows) {
                                    var row = $scope.rows[i];
                                    if (id == row.id) {
                                        $scope.data = row;
                                        return;
                                    }
                                }
                            }
    
                            //移除
                            $scope.remove = function(id) {
                                for ( var i in $scope.rows) {
                                    var row = $scope.rows[i];
                                    if (id == row.id) {
                                        $scope.rows.splice(i, 1);
                                        return;
                                    }
                                }
                            }
    
                            //保存
                            $scope.save = function() {
                                $http({
                                    url : '/save',
                                    method : 'POST',
                                    data : $scope.data
                                }).success(function(r) {
                                    //保存成功后更新数据
                                    $scope.get(r.id);
                                });
                            }
    
                            //删除
                            $scope.del = function(id) {
                                $http({
                                    url : '/delete?id=' + id,
                                    method : 'POST',
                                }).success(function(r) {
                                    //删除成功后移除数据
                                    $scope.remove(r.id);
                                });
                            }
    
                            //获取数据
                            $scope.get = function(id) {
                                $http({
                                    url : '/get?id=' + id,
                                    method : 'POST',
                                }).success(function(data) {
                                    for ( var i in $scope.rows) {
                                        var row = $scope.rows[i];
                                        if (data.id == row.id) {
                                            row.no = data.no;
                                            row.date = data.date;
                                            row.quantity = data.quantity;
                                            return;
                                        }
                                    }
                                    $scope.rows.push(data);
                                });
                            }
    
                            //初始化载入数据
                            $http({
                                url : '/findAll',
                                method : 'POST'
                            }).success(function(rows) {
                                for ( var i in rows) {
                                    var row = rows[i];
                                    $scope.rows.push(row);
                                }
                            });
    
                            $scope.findAllByNoLike = function() {
                                $http(
                                        {
                                            url : '/findAllByNoLike',
                                            method : 'POST',
                                            headers : {
                                                'Content-Type' : 'application/x-www-form-urlencoded'
                                            },
                                            data : 'no=' + $scope.no
                                        }).success(function(rows) {
                                    $scope.rows = rows;
                                });
                            };
    
                            $scope.findAllByDateBetween = function() {
                                $http(
                                        {
                                            url : '/findAllByDateBetween',
                                            method : 'POST',
                                            headers : {
                                                'Content-Type' : 'application/x-www-form-urlencoded'
                                            },
                                            data : 'startDate=' + $scope.startDate
                                                    + '&endDate=' + $scope.endDate
                                        }).success(function(rows) {
                                    $scope.rows = rows;
                                });
                            };
    
                            $scope.findAllByQuantityLessThan = function() {
                                $http(
                                        {
                                            url : '/findAllByQuantityLessThan',
                                            method : 'POST',
                                            headers : {
                                                'Content-Type' : 'application/x-www-form-urlencoded'
                                            },
                                            data : 'quantity=' + $scope.quantity
                                        }).success(function(rows) {
                                    $scope.rows = rows;
                                });
                            };
                        });
    
        /*]]>*/
    </script>
    </head>
    <body ng-app="app" ng-controller="MainController">
        <h1>玩转spring boot——结合JPA</h1>
        <h4>
            <a href="http://www.cnblogs.com/GoodHelper/">from 刘冬的博客</a>
        </h4>
        <input type="button" value="添加" ng-click="add()" />
        <input type="button" value="保存" ng-click="save()" />
        <br />
        <br />
        <h3>订单信息:</h3>
        <input type="hidden" ng-model="data.id" />
        <table cellspacing="1" style="background-color: #a0c6e5">
            <tr>
                <td>编号:</td>
                <td><input ng-model="data.no" /></td>
                <td>日期:</td>
                <td><input ng-model="data.date" /></td>
                <td>数量:</td>
                <td><input ng-model="data.quantity" /></td>
            </tr>
        </table>
        <br />
        <h3>查询条件:</h3>
    
        <table cellspacing="1" style="background-color: #a0c6e5">
            <tr>
                <td>编号:</td>
                <td><input ng-model="no" /></td>
                <td><input type="button" ng-click="findAllByNoLike()"
                    value="like查询" /></td>
            </tr>
            <tr>
                <td>日期:</td>
                <td><input ng-model="startDate" /><input ng-model="endDate" /></td>
                <td><input type="button" ng-click="findAllByDateBetween()"
                    value="between查询" /></td>
            </tr>
            <tr>
                <td>数量:</td>
                <td><input ng-model="quantity" /></td>
                <td><input type="button" ng-click="findAllByQuantityLessThan()"
                    value="小于查询" /></td>
            </tr>
        </table>
    
        <br />
        <h3>订单列表:</h3>
        <table cellspacing="1" style="background-color: #a0c6e5">
            <tr
                style="text-align: center; COLOR: #0076C8; BACKGROUND-COLOR: #F4FAFF; font-weight: bold">
                <td>操作</td>
                <td>编号</td>
                <td>日期</td>
                <td>数量</td>
            </tr>
            <tr ng-repeat="row in rows" bgcolor='#F4FAFF'>
                <td><input ng-click="edit(row.id)" value="编辑" type="button" /><input
                    ng-click="del(row.id)" value="删除" type="button" /></td>
                <td>{{row.no}}</td>
                <td>{{row.date}}</td>
                <td>{{row.quantity}}</td>
            </tr>
        </table>
    
        <br />
        <a href="http://www.cnblogs.com/GoodHelper/">点击访问原版博客</a>
    </body>
    </html>
    index.html

    运行效果:

    like查询:

    日期区间查询:

    小于查询:

     总结


     JPA的知识点很多,只用一篇博客是介绍不完的,可能一本书都不一定讲完。等以后有机会希望我再写一个关于JPA的系列。也可以在本系列后面的实践篇中写一些与spring boot更多结合的内容。

    也可以在文档中查询到JPA的属性表达式和JPQL表达式的API:

    http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions

    http://docs.oracle.com/javaee/6/tutorial/doc/gjivm.html

    http://www.objectdb.com/api/java/jpa/queries

    代码:https://github.com/carter659/spring-boot-05.git

    如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。

    有可能就是你的一点打赏会让我的博客写的更好:)

    玩转spring boot系列目录

  • 相关阅读:
    浅谈均值、方差、标准差、协方差的概念及意义
    数据库设计的基本步骤
    VS添加lib库
    Android activity_main.xml删除边缘距离,充满屏幕
    Android 设置旋转朝向
    WebStorm注册码
    VS禁止特定警告
    VS 高亮显示不带后缀的C++头文件
    VS2010设置C++包含目录和库目录
    读取STL模型
  • 原文地址:https://www.cnblogs.com/GoodHelper/p/6227944.html
Copyright © 2020-2023  润新知