发布于2026-06-02 阅读(0)
扫一扫,手机访问
JPA,全称Ja va Persistence API,是Ja va官方定义的一套ORM规范。严格来说,它只是一套接口规范,并没有提供底层的实现。这背后其实是典型的抽象工厂设计模式——定义与实现解耦。那么哪些框架实现了JPA?Hibernate、TopLink都是JPA的提供商,它们各自实现了这套规范。
JPA最方便的地方在于,它基于注解就能搞定实体类到关系表之间的映射。常用的注解就那么几个:
具体怎么用,官方参考文档里都有,这里就不赘述了。
这次的任务是用MySQL提供的实例数据库world,基于JPA设计两个实体——City和Country,来映射数据库中已存在的表。最终要实现多表连接查询,并在UI界面上分页显示每个城市的信息,包括:编号、城市名称、城市人口、所在国家、所属洲。
要点:根据city表中的countrycode字段,与country表中的code字段进行匹配,完成多表查询。



先看City实体:
import ja vax.persistence.Entity;
import ja vax.persistence.GeneratedValue;
import ja vax.persistence.GenerationType;
import ja vax.persistence.Id;
import ja vax.persistence.JoinColumn;
import ja vax.persistence.ManyToOne;
import ja vax.persistence.OneToOne;
import ja vax.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;
}
@Override
public String toString() {
return "City [id=" + id + ", name=" + name + ", population=" + population + ", country=" + country + "]";
}
}
再看Country实体:
import ja vax.persistence.Entity;
import ja vax.persistence.GeneratedValue;
import ja vax.persistence.GenerationType;
import ja vax.persistence.Id;
import ja vax.persistence.Table;
@Entity
@Table(name = "country")
public class Country {
@Id
String 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;
}
@Override
public String toString() {
return "Country [code=" + code + ", name=" + name + ", continent=" + continent + "]";
}
}
Repository层不需要自定义业务逻辑,直接继承接口就行——注意这里用的是PagingAndSortingRepository,它本身就支持分页和排序。
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; @Repository public interface CityRepository extends PagingAndSortingRepository{ }
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; @Repository public interface CountryRepository extends PagingAndSortingRepository{ }
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";
}
}
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 {
@Autowired
CityRepository cityRepository;
/**
* GET '/api/city'
*
* @param page 当前页码
* @param size 每页的记录数默认设定为10,一页加载10条
* @return
*/
@GetMapping
public Page 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);
}
}
前端用Vue + AJAX (axios) + Bootstrap来呈现,分页逻辑都写在了Vue实例里,包括上一页、下一页、页码快速定位,以及页码过多时的省略号显示。直接看代码:
City
Cities Of The World
基于
JPA
分页显示
编号
城市名称
城市人口 [↓]
所在国家
所属洲
{{city.id}}
{{city.name}}
{{city.population}}
{{city.country.name}}
{{city.country.continent}}
-
Previous
-
{{showPage(n)}}
-
Next
-
转到 页
每页显示10条记录,一共切分成408页,按照城市人口降序排序。这是最终的效果:

通过这个示例,可以清晰看到JPA如何通过`@ManyToOne`和`@JoinColumn`实现多表连接查询,再配合Spring Data的`PagingAndSortingRepository`实现分页与排序,最后用前端Vue + Bootstrap呈现出一个完整的分页表格。整个流程环环相扣,非常适合作为JPA多表查询的实际入门参考。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8