JDBC
最底層技術規範(相對於JPA而言)
定義:java語言連接關係數據庫進行SQL操作的規範,各個數據庫廠商實現了該規範(JDBC驅動程序)。
MyBatis
定義:基於java實現的SQL映射框架,
封裝了JDBC操作。
完成的是SQL到方法,實現是半自動化的。
容易理解。
Hibernate(冬眠)
定義:基於java實現的ORM(對象關係映射)框架,
封裝了JDBC操作。
類直接映射表,實現是自動化的,高度封裝。Domain model persistence for relational databases
領域模型(業務對象)持久化到關係數據庫
JPA
Java Persistence API (JPA) specification
hibernate是JPA的一種參考實現。
JPA的一個實現:Hibernate,TopLink,
JPA是技術規範,抽象的定義。如:碳酸飲料,啤酒。
Hibernate是一個實現 。如 可樂,雪碧。
三者的聯繫
JDBC是技術規範,實現:mysql,db2,oracle,postgreSQL,
只使用JDBC中的API,看不到廠商的影子,實際的工作都是廠商驅動完成的。MyBatis:SQL映射,介於兩者之間。
Spring Data JDBC
JPA是技術規範,實現:hiberbnate,topLink
Spring Data JPA默認使用了hibernate,切換到toplink實現,編碼時只是用JPA的API,
看不到hibernate的影子。
JDBC和JPA的區別
JDBC,JPA 都是 Java 語言中定義的技術規範,JDBC 連接關係數據庫,執行 SQL 語言,
JPA 建立在 JDBC 之上,封裝 JDBC ,JPA 的方法操作,底層是 JDBC。
MySQL默認連接是150個
代碼演示
先創建一個工程目錄,選擇工程所需的依賴
工程目錄如圖:
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
現在可以來看看效果:
從數據庫取得的數據
前端上渲染:(之前設置爲一頁有300條記錄)