【Spring Boot JPA】ManyToOne OneToMany学习笔记

时间: 2023-07-10 admin IT培训

【Spring Boot JPA】ManyToOne OneToMany学习笔记

【Spring Boot JPA】ManyToOne OneToMany学习笔记

Spring Data JPA的官方文档参考:/

我希望使用JPA进行两个表的一对多和多对一的关系:

相册(Album)1 : N 相片(Photo)

Album的定义为:

import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.Data;import javax.persistence.*;
import java.util.List;@Entity
@Table(name = "t_album")
@Data
public class Album {@Idprivate String id;@Columnprivate String name;@JsonManagedReference@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "album")private List<Photo> photos;
}

Photo的定义为:

import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.Data;import javax.persistence.*;@Entity
@Table(name = "t_photo")
@Data
public class Photo {@Idprivate String id;@Columnprivate String name;@JsonBackReference@ManyToOne(cascade = CascadeType.REFRESH)@JoinColumn(name="album_id", referencedColumnName = "id")private Album album;
}

说明:

jackson中的@JsonBackReference和@JsonManagedReference,以及@JsonIgnore均是为了解决对象中存在双向引用导致的无限递归(infinite recursion)问题。这些标注均可用在属性或对应的get、set方法中。  
@JsonBackReference和@JsonManagedReference:这两个标注通常配对使用,通常用在父子关系中。@JsonBackReference标注的属性在序列化(serialization,即将对象转换为json数据)时,会被忽略(即结果中的json数据不包含该属性的内容)。@JsonManagedReference标注的属性则会被序列化。在序列化时,@JsonBackReference的作用相当于@JsonIgnore,此时可以没有@JsonManagedReference。但在反序列化(deserialization,即json数据转换为对象)时,如果没有@JsonManagedReference,则不会自动注入@JsonBackReference标注的属性(被忽略的父或子);如果有@JsonManagedReference,则会自动注入自动注入@JsonBackReference标注的属性。  
@JsonIgnore:直接忽略某个属性,以断开无限递归,序列化或反序列化均忽略。当然如果标注在get、set方法中,则可以分开控制,序列化对应的是get方法,反序列化对应的是set方法。在父子关系中,当反序列化时,@JsonIgnore不会自动注入被忽略的属性值(父或子),这是它跟@JsonBackReference和@JsonManagedReference最大的区别。

Album的Repository定义:

import com.example.jpa.model.Album;
import org.springframework.data.jpa.repository.JpaRepository;public interface AlbumRepository extends JpaRepository<Album, String> {
}

Photo的Repository定义:

import com.example.jpa.model.Album;
import com.example.jpa.model.Photo;
import org.springframework.data.jpa.repository.JpaRepository;import java.util.List;public interface PhotoRepository extends JpaRepository<Photo, String> {public List<Photo> findByAlbum(Album album);
}

说明:findByAlbum是希望获取一个相册中所有的照片

Album的Restful服务:

import com.example.jpa.model.Album;
import com.example.jpa.model.Photo;
import com.example.jpa.repository.AlbumRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import java.util.List;
import java.util.Optional;@RestController
public class AlbumService {@AutowiredAlbumRepository albumRepository;@RequestMapping(value = "/album", method = RequestMethod.POST)public Album addAlbum(@RequestBody Album album) {return albumRepository.save(album);}@RequestMapping(value = "/album", method = RequestMethod.GET)public List<Album> getAllAlbum() {return albumRepository.findAll();}@RequestMapping(value = "/album/photo", method = RequestMethod.GET)public List<Photo> getAlbumPhoto(@RequestBody Album album) {Optional<Album> optional = albumRepository.findOne(Example.of(album));return optional.get().getPhotos();}
}

Photo的Restful服务:

import com.example.jpa.model.Album;
import com.example.jpa.model.Photo;
import com.example.jpa.repository.PhotoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
public class PhotoService {@AutowiredPhotoRepository photoRepository;@RequestMapping(value = "/photo", method = RequestMethod.POST)public Photo addPhoto(@RequestBody Photo photo) {return  photoRepository.save(photo);}@RequestMapping(value = "/photo/all", method = RequestMethod.GET)public List<Photo> getAllPhotos() {return photoRepository.findAll();}@RequestMapping(value = "/photo/album", method = RequestMethod.GET)public List<Photo> getAlbumPhotos(@RequestBody Album album) {return photoRepository.findByAlbum(album);}
}

pom文件定义为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=".0.0" xmlns:xsi=""xsi:schemaLocation=".0.0 .0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>jpa</artifactId><version>0.0.1-SNAPSHOT</version><name>jpa</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- .projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version><scope>provided</scope></dependency><!-- .alibaba/fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.60</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.properties配置文件:

#配置数据库连接地址
spring.datasource.primary.jdbc-url=jdbc:h2:mem:testdb
#;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=TRUE
#配置数据库驱动
spring.datasource.primary.driver-class-name=org.h2.Driver
#配置数据库用户名
spring.datasource.primary.username=sa
#配置数据库密码
spring.datasource.primary.password=
#配置能远程访问
spring.h2.console.settings.web-allow-others=true
#配置访问地址
spring.h2.console.path=/h2-console
#配置项目启动 h2就启动
spring.h2.console.enabled=true

现在启动服务,使用PostMan进行测试:

添加Album:

POST: http://127.0.0.1:8080/album

Body:

{
    "id":"album1",
    "name":"the album1"
}

添加Photo:

POST: http://127.0.0.1:8080/photo

Body:

{
    "id":"photo1",
    "name":"the photo1",
    "album":{
        "id":"album1"
    }
}

查询Album中的Photo:

GET: http://127.0.0.1:8080/album/photo

Body:

{
    "id":"album1"
}