Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在Spring Boot中从双向表关系生成DTO_Sql_Json_Spring Boot_Hibernate_Jpa - Fatal编程技术网

Sql 如何在Spring Boot中从双向表关系生成DTO

Sql 如何在Spring Boot中从双向表关系生成DTO,sql,json,spring-boot,hibernate,jpa,Sql,Json,Spring Boot,Hibernate,Jpa,早上好,很高兴见到你 我最近刚接触Spring Boot,我正在使用REST API,它基本上是一个包含歌曲的播放列表,基本上REST API应该具有以下结构。一个播放列表可以有许多歌曲: { "name": "Lista 1", "description": "Lista de reproduccion 2020 spotify", "songs": [

早上好,很高兴见到你

我最近刚接触Spring Boot,我正在使用REST API,它基本上是一个包含歌曲的播放列表,基本上REST API应该具有以下结构。一个播放列表可以有许多歌曲:

{
    "name": "Lista 1",
    "description": "Lista de reproduccion 2020 spotify",
    "songs": [
        {
            "title": "Tan Enamorados",
            "artist": "CNCO",
            "album": "Tan Enamorados",
            "year": 2020,
            "playList": 1
        },
        {
            "title": "Hawai",
            "artist": "Maluma",
            "album": "PAPI JUANCHO",
            "year": 2020,
            "playList": 1
        }
    ]
}
目前,这是我配置实体的方式

实体歌曲

@Entity
@Table(name = "SONGS")
public class Songs{

    @JsonIgnore
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ID")
    private Long id;

    @Column(name = "title")
    private String title;

    @Column(name = "artist")
    private String artist;

    @Column(name = "album")
    private String album;

    @Column(name = "year")
    private int year;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PLAY_LIST_ID")
    private PlayList playList;

    public Long getId() {
        return this.id;
    }

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

    public String getTitle() {
        return this.title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArtist() {
        return this.artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getAlbum() {
        return this.album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public int getYear() {
        return this.year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public PlayList getPlayList() {
        return this.playList;
    }

    public void setPlayList(PlayList playList) {
        this.playList = playList;
    }
 
}
实体播放列表

@Entity
@Table(name = "PLAY_LIST")
public class PlayList {

    @JsonIgnore
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ID")
    private Long id;

   
    @Column(name="name")
    private String name;

    
    @Column(name="description")
    private String description;


    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "playList")
    private List<Songs> songs = new ArrayList<>();


    public Long getId() {
        return this.id;
    }

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

    public String getName() {
        return this.name;
    }

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

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    public List<Songs> getSongs() {
        return this.songs;
    }

    public void setSongs(List<Songs> songs) {
        this.songs = songs;
    }
    
}
这是由于歌曲实体中的playList字段,当尝试获取包含歌曲的播放列表时,我会得到一个递归数组,而不是播放列表的id,这是我想要得到的,实际情况是,我得到了如下内容:

我可以通过在字段中应用JsonIgnore来解决问题,但是这会影响我,当我去保存播放列表时,我无法将idPlayList字段传递给每首歌曲,以确保每首歌曲都与其各自的idPlayList一起保存

我认为最好的办法是在这里建立一个DTO,帮助我建立两个表之间的关系,但是,我不知道如何才能做到这一点,在执行播放列表的get时,只获取idPlayList,在省电时,将idPlayList传递到将与播放列表一起保存的每首歌曲中,或者,如果有另一种方式,我可以存储一个播放列表及其歌曲,并将其直接存储,因为目前我必须由BD为每首歌曲分配idPlayList

  • spring.jpa.open in view=false
    添加到
    application.properties
    中,使其具有
    LazyInitializationException
    。这将有助于构建良好的查询。

  • 使用JPQL查询加载
    播放列表
    歌曲
    ,使用
    左连接获取
    来获取列表中的歌曲。因此,
    歌曲
    将已加载,歌曲中的
    播放列表
    将延迟<代码>@EntityGraph也可以使用

    select list from PlayList list left join fetch list.songs where list.id = :listId
    
  • Jackson中有
    hibernate5模块
    。它允许省略惰性关联。因此,杰克逊不会触碰歌曲中的播放列表。

  • 建立一个真正的系统。您可以添加
    播放响应
    歌曲响应
    类,并将实体映射到服务级别上的这些类。在这种情况下,您可能不需要
    Hibernate5Module
    。但最好也尝试一下这个模块

  • 使用启用数据库登录
    application.properties

  • 仔细检查日志中的事务和SQL。不要让Hibernate产生不必要的查询

    如何使用列表保存歌曲

    将此方法添加到播放列表中

    @Transient
    public void addSong(Song song) {
        song.setPlayList(this);
        songs.add(song);
    }
    
    使用
    addSong()
    方法将歌曲添加到列表中


    保存播放列表。Hibernate将使用正确的列表id保存列表中的所有歌曲,因为存在
    cascade=CascadeType。在
    @OneToMany

    公共类歌曲中的所有歌曲必须是
    Song
    。这是一条记录,不是所有的记录:)谢谢你的回答,你能给我一个左连接提取的例子吗?如果您可以将播放列表与他们的歌曲进行映射。@CesarJusto I updatedI一直在阅读@EntityGraph,这非常好,因为它可以提高查询的性能,但是,我仍然不明白如何加载(插入)包含歌曲的播放列表,由于播放列表的id是自动生成和自动递增的,因此我不知道如何将其关联,以便将歌曲与其id_播放列表值一起保存,从而保持与播放列表的关联playList@CesarJusto我更新了Hanks,我将测试更改,我会告诉你
    @Repository
    public interface PlayListRepository extends JpaRepository<PlayList, Long> {
    
        Optional<PlayList> findById(Long Id);
        
    }
    
    org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.example.api.songs.entity.PlayList[\"songs\"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.api.songs.entity.Songs[\"playList\"]->com.example.api.songs.entity.PlayList[\"songs\"]->org.hibernate.
    
    select list from PlayList list left join fetch list.songs where list.id = :listId
    
    logging.level.org.springframework.transaction.interceptor=TRACE
    logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG
    
    logging.level.org.hibernate.SQL=DEBUG
    spring.jpa.properties.hibernate.use_sql_comments=true
    
    @Transient
    public void addSong(Song song) {
        song.setPlayList(this);
        songs.add(song);
    }