基于 JPA 显示城市信息

  • 一、JPA
    • JPA 定义
  • 二、任务
    • 实战
      • 1.项目结构
      • 2.项目配置信息
      • 3.实体
      • 4.映射
      • 5.控制器
      • 6.UI
    • 三、效果图

一、JPA

JPA 定义

  • Java 持久化 API
  • Java 官方定义的 ORM 规范,只是一套规范,并没有提供底层的实现(基于抽象工厂设计模式,将定义与实现解耦),Hibernate 、TopLink 都是 JPA 的提供商,它们实现了 JPA 规范
  • JPA 基于注解的方式实现了 实体类 到 关系表 之间的映射
    • @Entity
    • @Table
    • @Id
    • @Column
    • @OneToOne
    • @OneToMany
    • @ManyToOne

JPA 官方参考文档

二、任务

使用 MySQL 提供的实例数据库 world,基于 JPA 设计两个实体 City 和 Country 映射数据库中已存在的表,实现多表连接查询,在 UI 界面分页显示每个城市的信息:

  • 编号
  • 城市名称
  • 城市人口
  • 所在国家
  • 所属洲

要点:根据 city 表中的 countrycode 字段 与 country 表中的 code 字段进行匹配,实现多表查询

实战

1.项目结构

2.项目配置信息

3.实体

  • City
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;@Entity
@Table(name = "city")
public class City {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)Long id;String name;Long population;@ManyToOne//(targetEntity = Country.class)@JoinColumn(name="countrycode",referencedColumnName = "code")Country country;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 Long getPopulation() {return population;}public void setPopulation(Long population) {this.population = population;}public Country getCountry() {return country;}public void setCountry(Country country) {this.country = country;}@Overridepublic String toString() {return "City [id=" + id + ", name=" + name + ", population=" + population + ", country=" + country + "]";}}
  • Country
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;@Entity
@Table(name = "country")
public class Country {@IdString code;String name;String continent;public Country() {}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getContinent() {return continent;}public void setContinent(String continent) {this.continent = continent;}@Overridepublic String toString() {return "Country [code=" + code + ", name=" + name + ", continent=" + continent + "]";}}

4.映射

  • CityRepository
    无需自定义业务逻辑,直接继承接口即可,该接口支持分页和排序
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;@Repository
public interface CityRepository extends PagingAndSortingRepository<City, Long>{}
  • CountryRepository
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CountryRepository extends PagingAndSortingRepository<Country, String>{}

5.控制器

  • HomeController
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class HomeController {// 返回视图@GetMapping("/")public String home() {return "index.html";}
}
  • CityController
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;@RestController
@RequestMapping("/api/city")
public class CityController {@AutowiredCityRepository cityRepository;/*** GET '/api/city'* * @param page 当前页码* @param size 每页的记录数默认设定为10,一页加载10条* @return*/@GetMappingpublic Page<City> findCity(@RequestParam(name = "p",defaultValue = "0") int page,@RequestParam(name = "n",defaultValue = "10") int size){// 分页规则Pageable pageable = PageRequest.of(page, size);// 可按城市人口数量进行降序排序pageable = PageRequest.of(page, size,Sort.by("population").descending());return cityRepository.findAll(pageable);}}

6.UI

基于 Vue、AJAX、Bootstrap

<!doctype html>
<html lang="en"><head><title>City</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"><!-- Vue js--><script src="js/vue.js"></script><!-- AJAX js--><script src="js/axios.min.js"></script>
</head><body><!-- View UI--><div id="app"><!-- 展板 --><div class="jumbotron jumbotron-fluid py-1 pl-5 mb-0"><div class="container"><h1 class="display-3">Cities Of The World</h1><p class="lead">基于 <span class="badge badge-pill badge-danger">JPA</span> 分页显示</p><p class="lead">作者:某某某</p></div></div><!-- 容器 --><div class="container-fluid"><!-- 表格 --><table class="table table-striped table-bordered mt-2"><!-- 表头 --><thead class="table-dark"><tr class="text-center"><th style="width: 3em;"><input type="checkbox"></th><th style="width: 8em;">编号</th><th style="width: 20em;">城市名称</th><th style="width: 10em;">城市人口 [↓]</th><th>所在国家</th><th style="width: 18em;">所属洲</th></tr></thead><!-- 表体 --><tbody><!-- v-for 声明式渲染 城市数据 --><tr v-for="(city, index) in cityList" :key="index"><td class="text-center"><input type="checkbox"></td><td class="text-center">{{city.id}}</td><td>{{city.name}}</td><td>{{city.population}}</td><td>{{city.country.name}}</td><td>{{city.country.continent}}</td></tr></tbody></table></div><!-- 分页导航 --><nav aria-label="Page navigation"><ul class="pagination justify-content-center"><!-- 上一页 --><li class="page-item" @click="prevPage()" :class="{'disabled':isFirst}"><a class="page-link" href="#" aria-label="Previous"><span aria-hidden="true">上一页</span><span class="sr-only">Previous</span></a></li><!-- v-for 声明式渲染 页码 --><li class="page-item" :class="{active : (n-1)===currentPage}" @click="page(n-1)" v-for="n in totalPages" v-if="showPage(n)" :key="n"><a class="page-link" href="#">{{showPage(n)}}</a></li><!-- 下一页 --><li class="page-item" @click="nextPage()" :class="{'disabled':isLast}"><a class="page-link" href="#" aria-label="Next"><span aria-hidden="true">下一页</span><span class="sr-only">Next</span></a></li><!-- 页码快速定位 --><li><!-- 输入页码按回车键即可跳转 或者 点击跳转按钮-->转到 <input @keyup.enter="goPage()" style="width: 3em;" type="text" v-model="goPageIndex"> 页<button class="btn btn-outline-warning " @click="goPage()">跳转</button></li></ul></nav></div><!-- JS --><Script>// 创建一个 Vue 实例let v = new Vue({// 绑定el: '#app',// 数据data: {// 城市列表cityList: [],// 总页码totalPages: 0,// 当前页码currentPage: 0,// 是否第一页isFirst: '',// 是否最后一页isLast: '',// 输入的页码goPageIndex: ''},// 方法methods: {// 加载数据loadCityList: function() {// GET '/api/city'const url = '/api/city';axios.get(url).then(res => {console.log('加载城市列表数据', res.data);// 城市列表this.cityList = res.data.content;// 当前页this.currentPage = res.data.number;// 总页数this.totalPages = res.data.totalPages;// 状态this.isFirst = res.data.first;this.isLast = res.data.last;}).catch(err => {console.error(err);})},// 点击页码进行跳转page: function(n) {// GET '/api/city?p=123'const url = `/api/city?p=${n}`;axios.get(url).then(res => {console.log('换页', n + 1);this.cityList = res.data.content;this.totalPages = res.data.totalPages;this.currentPage = res.data.number;}).catch(err => {console.error(err);})},// 上一页prevPage: function() {if (this.currentPage > 0) {this.currentPage -= 1;this.page(this.currentPage);} else {return;}},// 下一页nextPage: function() {if (this.currentPage < this.totalPages - 1) {this.currentPage += 1;this.page(this.currentPage);} else {return;}},// 输入页码快速定位goPage: function() {let goPageIndex = parseInt(this.goPageIndex);if (goPageIndex > 0 && goPageIndex <= this.totalPages) {this.page(this.goPageIndex - 1);this.goPageIndex = '';}},// 页码过多时显示省略号showPage(n) {// 前两个和最后两个始终显示if (n < 3 || (n > this.totalPages - 2)) {return n;}// 当前页的前一页和后一页始终显示 else if (n <= this.currentPage + 2 && n >= this.currentPage) {return n;}// 当前页的前前页和后后页显示 ... else if (n === this.currentPage + 3 || n === this.currentPage - 1) {return '...';}// 其余的不显示 else {return false;}}},// 回调函数// 创建页面时自动调用 加载数据created() {this.loadCityList();},})</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>

三、效果图

每页10条记录,切分成408页,按照城市人口进行降序排序

基于JPA实现多表连接查询相关推荐

  1. mysql select符合查询_数据库select group by 和having语句 多表连接查询 复合查询

    1.SELECT --group by 子句 group by子句按照指定的列column_name对表数据进行分组 group by 后面跟的列也叫分组特性列 使用group by后,能选择的列   ...

  2. mysql 连接查询两个条件_MySQL之多表查询一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习...

    一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 首先说一下,我们写项目一般都会建一个数据库,那数据库里面是不是存了好多张表啊,不可能把所有的数据都放到一张表里面,肯定要分表来存数据,这样节 ...

  3. SQLServer学习笔记八:多表连接查询

    学习目标 掌握多表连接查询的概念 学会使用内连接查询数据 学会使用外连接查询数据 学会使用UNION合并查询结果 前面学习的内容都是基于单个数据库表的查询,下面将学习涉及多个表的数据查询. 多表连接查 ...

  4. 单表查询和多表连接查询哪个效率更快?

    这段时间在做项目的过程中,遇到一个模块,数据之间的联系很复杂,在建表的时候就很纠结,到底该怎么去处理这些复杂的数据呢,是单表查询,然后在业务层去处理数据间的关系,还是直接通过多表连接查询来处理数据关系 ...

  5. SQL多表连接查询(具体实例)

    本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:student  截图例如以下: 表2:course  截图例如以下: (此时这样建表仅仅是为了演示连接SQL语句.当然实际开发中我们 ...

  6. SQL多表连接查询(详细实例)

    本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:student 截图如下: 表2:course 截图如下: (此时这样建表只是为了演示连接SQL语句,当然实际开发中我们不会这样建表, ...

  7. 解决Springboot+JPA中多表关联查询会查询多次的问题(n+1查询问题)

    解决Springboot+JPA中多表关联查询会查询多次的问题(n+1查询问题) 参考文章: (1)解决Springboot+JPA中多表关联查询会查询多次的问题(n+1查询问题) (2)https: ...

  8. 【2017-11-26】Linq表连接查询

    class Program{static void Main(string[] args){//Linq创建的数据库上下文对象dbDataClasses2DataContext db = new Da ...

  9. django model filter 条件过滤,及多表连接查询、反向查询,某字段的distinct

    2019独角兽企业重金招聘Python工程师标准>>> 1.多表连接查询:当我知道这点的时候顿时觉得django太NX了.   class A(models.Model):      ...

最新文章

  1. RYU控制器的学习笔记(三) 利用观察者模式通知app处理报文
  2. (三)ORB特征匹配
  3. Jquery简单的右侧浮动菜单
  4. STM32 - 定时器的设定 - 基础 - 05 - Arbitrary waveform generation using timer DMAburst feature - 任意波形的序列产生
  5. day24 java的集合(1)collection
  6. Log4j2 高危漏洞分析
  7. 10清理roaming文件夹_Win10系统的C盘哪些文件可以删除?C盘文件夹功能介绍
  8. 不能错过的linux驱动开发的经典书籍推荐
  9. 圈子论坛社区小程序,交友,博客,社交,陌生人社交,即时聊天 前后端开源PHP
  10. Tera Term 下载教程
  11. Ques1017勇者斗恶龙
  12. 【python技能树】python程序设计思想
  13. python电子表格类_python合并同类型excel表格的方法
  14. 从实际案例聊聊JDK 17 的GC优化
  15. 国人“急功近利”的理由和无奈
  16. 最后防线:字节跳动HIDS分析
  17. honor荣耀独立后发展的好吗?
  18. 资源管理Placement部署(Nova)
  19. 简单工厂 工厂方法 抽象工厂
  20. CGB2105-Day-09笔记

热门文章

  1. 恶意软件RIPPER解析——其如何盗取ATM机的巨额泰铢?
  2. Grid 与 Dock
  3. matlab数学建模练习(2)练习电子科技大学数学实验
  4. 商彝夏鼎丨明定陵和金丝蟠龙翼善冠
  5. 张豫湘个人博客-源来如此
  6. 2021年12月国产数据库排行榜: openGauss节节攀升拿下榜眼,GaussDB与TDSQL你争我夺各进一位
  7. 基础字符串函数及其模拟实现
  8. 企业打造智能工厂的核心系统——【MES系统】
  9. NLP文本分类 落地实战五大利器!
  10. IOS学习——TableViewController