JPA operation of data persistent storage

JDBC

     The bottom-most technical specification (relative to JPA)
     defines: the specification of java language to connect a relational database for SQL operation, and various database vendors implement the specification (JDBC driver) .


MyBatis

     Definition: SQL mapping framework based on java,
     encapsulating JDBC operations.
     The completion is SQL to method , and the implementation is semi-automatic .
     Easy to understand.


Hibernate

     Definition: ORM (Object Relational Mapping) framework based on java ,
                  encapsulates JDBC operations.
      Class direct mapping table, the implementation is automated and highly encapsulated.

      Domain model persistence for relational databases
       Domain model (business objects) persistence to relational databases


JPA

 

   The Java Persistence API (JPA) specification
     hibernate is a reference implementation of JPA.
    An implementation of JPA: Hibernate, TopLink,
    
    JPA is a technical specification, an abstract definition. Such as: carbonated drinks, beer.
    Hibernate is an implementation. Such as Coke, Sprite.


The connection between the three

   JDBC is a technical specification, implementation: mysql, db2, oracle, postgreSQL,
    only use the API in JDBC, can not see the shadow of the manufacturer, the actual work is done by the manufacturer driver.

    MyBatis: SQL mapping, somewhere in between.

    Spring Data JDBC

    JPA is a technical specification, implementation: hiberbnate, topLink
    Spring Data JPA uses hibernate by default, switch to toplink implementation, coding is only using JPA API,
    can not see the shadow of hibernate.
 

 


The difference between JDBC and JPA

   Both JDBC and JPA are technical specifications defined in the Java language. JDBC connects to a relational database and executes the SQL language.
    JPA is built on top of JDBC and encapsulates JDBC and JPA method operations. The bottom layer is JDBC.

 MySQL default connection is 150


Code demo

First create a project directory, select the required dependencies of the project


The project directory is shown in the figure: 

 


 City.java

package com.newer.jpa;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * POJO/Domain Object/使用JPA的注解进行ORM
 * 
 * 实体类映射到表,类的属性映射到表的列,不写 SQL,自动化
 * @author Admin
 *
 */
@Entity
//对应表名
@Table(name = "city")
public class City {
	
	//驼峰式命名法
	//+-------------+----------+------+-----+---------+----------------+
	//| Field       | Type     | Null | Key | Default | Extra          |
	//+-------------+----------+------+-----+---------+----------------+
	//| ID          | int      | NO   | PRI | NULL    | auto_increment |
	//| Name        | char(35) | NO   |     |         |                |
	//| CountryCode | char(3)  | NO   | MUL |         |                |
	//| District    | char(20) | NO   |     |         |                |
	//| Population  | int      | NO   |     | 0       |                |



//	             主键
		@Id
//		自增长
		@GeneratedValue
		Long id;
		
		@Column(name = "name", nullable = true)
		String name;
//		
		String countryCode;
		
//		类中属性名与表中列名一致时,可以不写注解
		String district;
		
		int population;
		
		
		public City() {
			
		}


		public Long getId() {
			return id;
		}


		public void setId(Long id) {
			this.id = id;
		}


		public String getName() {
			return name;
		}


		public void setName(String name) {
			this.name = name;
		}


		public String getCountryCode() {
			return countryCode;
		}


		public void setCountryCode(String countryCode) {
			this.countryCode = countryCode;
		}


		public String getDistrict() {
			return district;
		}


		public void setDistrict(String district) {
			this.district = district;
		}


		public int getPopulation() {
			return population;
		}


		public void setPopulation(int population) {
			this.population = population;
		}


		@Override
		public String toString() {
			return "City [id=" + id + ", name=" + name + ", countryCode=" + countryCode + ", district=" + district
					+ ", population=" + population + "]";
		}

		

		
	

}

CityRepository.java

package com.newer.jpa;

import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

/**
 * 数据持久化 操作
 * @author Admin
 *
 */
@Repository
public interface CityRepository extends PagingAndSortingRepository<City, Long>{

//	CRUD 基本操作 框架已经实现了,不需要你写了
	
//	排序,分页也实现了,不需要你写
	
//	TODO 额外的一些操作,需要自己实现
	
	
}

CityController.java

package com.newer.jpa;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Restful API定义实现
 * @author Admin
 *
 */
@RestController
//请求映射
@RequestMapping("/api/city")
public class CityController {

//	依赖service
//	也可以直接注入repository
	@Autowired
	CityRepository cityRepository;
	
	/**
	 * 分页获得数据:GET "/api/city ?p=0&s=20"
	 * 
	 * @RequestParam:字符串查询参数
	 * @param page 页码数,
	 * @param size 一页的记录数
	 * @return 分页信息:数据,总页数,当前页,当前页是否第一页等
	 */
	@GetMapping
	public Page<City> findAll(
			@RequestParam(name = "p" ,defaultValue = "0") int page,
			@RequestParam(name = "s",defaultValue = "300") int size
			) {
//		API是Spring Data设计
//		排序规则
//		order by name,id,desc
		Sort s1=Sort.by("name").ascending().and(Sort.by("id").descending());
		
//		order by name,id
		Sort s2=Sort.by("name","id");
//		分页信息
//		1.页码数,基于0开始的索引
//		2.记录数,20条记录
//		3.排序规则
//		Pageable pageable=PageRequest.of(0, 20,Sort.by("id"))	;
		
		Pageable pageable=PageRequest.of(page, size,Sort.by("id"))	;
		
		 return cityRepository.findAll(pageable);
	}
}

HomeController.java

package com.newer.jpa;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

	@GetMapping("/")
	public String home() {
		return "index.html";
	}
}

index.html

<!doctype html>
<html lang="en">

<head>
    <title>数据分页</title>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <!-- axios -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <!-- vue -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
    <div class="jumbotron jumbotron-fluid">
        <div class="container">
            <h1 class="display-3">数据分页</h1>
            <p class="lead">Vue & Spring Boot &MyBatis& MySQL</p>

        </div>
    </div>
    <div id="app" class="container">
        <h1>{{totalPages}}</h1>
        <!-- 表格 -->
        <table class="table">
            <thead>
                <tr>
                    <th>编号</th>
                    <th>城市</th>
                    <th>国家</th>
                    <th>所在地区</th>
                    <th>人口</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(city, index) in  cityList" :key="index">
                    <td>{{city.id}}</td>
                    <td>{{city.name}}</td>
                    <td>{{city.countryCode}}</td>
                    <td>{{city.district}}</td>
                    <td>{{city.population}}</td>
                </tr>

            </tbody>
        </table>

        <!-- 分页 -->
        <nav aria-label="Page navigation">
            <ul class="pagination justify-content-center">
                <li class="page-item ">
                    <a class="page-link" href="#" aria-label="Previous">
                        <span @click="page(index--)" aria-hidden="true" :class="{active: index===number}">上一页</span>

                    </a>
                </li>
                <!-- 默认的样式 -->
                <!-- <li class="page-item active"><a class="page-link" href="#">当前</a></li> -->


                <li v-for="(n, index) in  totalPages" :key="index" class="page-item" :class="{active: n-1===number}">

                    <a @click="page(n-1)" class="page-link" href="#">
                        {{n}}
                    </a>
                </li>
                <li class="page-item">
                    <a class="page-link" href="#" aria-label="Next">
                        <span @click="page(index++)" aria-hidden="true" :class="{active: index===number}">下一页</span>

                    </a>
                </li>
            </ul>
        </nav>

    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                cityList: [],
                // 总页数
                totalPages: '',
                // 当前页
                number: '',
                index: 1
            },
            methods: {
                page: function (num) {

                    axios.get('/api/city', {
                        params: {
                            p: num
                        }
                    })
                        .then(res => {
                            // console.log(res);
                            this.cityList = res.data.content;
                            this.totalPages = res.data.totalPages;
                            this.number = res.data.number;
                        })
                },

                next: function (i) {
                    axios.get('/api/city', {
                        params: {
                            p: i
                        }
                    })
                        .then(res => {
                            console.log(res);
                        })
                }
            },
            created() {
                // 本地URL
                let url = '/api/city';
                axios.get(url)
                    .then(res => {
                        console.log(res)
                        this.cityList = res.data.content;
                        this.totalPages = res.data.totalPages;
                        this.number = res.data.number;
                    })
                    .catch(err => {
                        console.error(err);
                    })
            },
        })

    </script>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
        integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
        crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
        integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
        integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
        crossorigin="anonymous"></script>
</body>

</html>

application.properties

#数据源
spring.datasource.url=jdbc:mysql://阿里云数据库ip:3306/world
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#请求参数
spring.http.log-request-details=true

#Spring MVC
logging.level.web=debug

#数据源默认的数据库连接池信息
logging.level.com.zaxxer=debug

#hibernate(JPA)
logging.level.org.hibernate.sql=debug

#jpa/hibernate 驼峰命名规则的映射
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

Now we can take a look at the effect:

Data obtained from the database


Rendering on the front end: (previously set to 300 records per page)

 

Published 125 original articles · praised 279 · 20,000+ views

Guess you like

Origin blog.csdn.net/weixin_44364444/article/details/105450845