JPA基于一个共同实体连接2个实体。

huangapple go评论70阅读模式
英文:

JPA join 2 Entity based upon 1 common entity

问题

package com.example.demo.model;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "country")
public class Country {

    @Id
    @Column(name = "countryid")
    private int countryId;
    @Column(name = "countryname")
    private String countryName;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "country")
    private List<CountryRegion> regions = new ArrayList<>();

    public int getCountryId() {
        return countryId;
    }

    public void setCountryId(int countryId) {
        this.countryId = countryId;
    }

    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }

    public List<CountryRegion> getRegions() {
        return regions;
    }

    public void setRegions(List<CountryRegion> regions) {
        this.regions = regions;
    }
}

package com.example.demo.model;

import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "region")
public class Region {

    @Id
    @Column(name = "regionid")
    private int regionId;
    @Column(name = "regionname")
    private String regionName;

    @OneToMany(mappedBy = "region", fetch = FetchType.LAZY)
    private List<CountryRegion> countries = new ArrayList<>();

    public int getRegionId() {
        return regionId;
    }

    public void setRegionId(int regionId) {
        this.regionId = regionId;
    }

    public String getRegionName() {
        return regionName;
    }

    public void setRegionName(String regionName) {
        this.regionName = regionName;
    }

    public List<CountryRegion> getCountries() {
        return countries;
    }

    public void setCountries(List<CountryRegion> countries) {
        this.countries = countries;
    }
}

package com.example.demo.model;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "countryregion1")
public class CountryRegion implements Serializable {

    @Id
    @ManyToOne
    @JoinColumn(name = "regionid", referencedColumnName = "regionId")
    private Region region;

    @Id
    @ManyToOne
    @JoinColumn(name = "countryid", referencedColumnName = "countryId")
    private Country country;

    public Region getRegion() {
        return this.region;
    }

    public void setRegion(Region region) {
        this.region = region;
    }

    public Country getCountry() {
        return this.country;
    }

    public void setCountry(Country country) {
        this.country = country;
    }
}

package com.example.demo.dao;

import com.example.demo.model.Country;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface CountryRepository extends CrudRepository<Country, Integer> {

    @Override
    List<Country> findAll();
}

package com.example.demo.dao;

import com.example.demo.model.Region;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface RegionRepository extends CrudRepository<Region, Integer> {

    @Override
    List<Region> findAll();
}

Please note that the changes I made are as follows:

  1. Changed the fetch attribute in the @OneToMany annotations to FetchType.LAZY to avoid unnecessary eager loading.
  2. Removed the @JsonBackReference annotation, as it's not needed in this case.
  3. Made sure that the CountryRegion class has proper associations with Country and Region using the @ManyToOne annotations.
  4. Please ensure that your controller and service are properly implemented to expose the required API to fetch data.

This code should help you avoid the infinite loop issue while serializing to JSON.

英文:

I have 3 tables - Country, Region and CountryRegion.

  1. Country - countryId(PK), countryName
  2. Region - regionId(PK), regionName
  3. CountryRegion - countryId(FK), regionId(FK)

I want to fetch list of countries when I fetch region. like :

*

{
regionId:11
regionName:&quot;abc&quot;
countries: [
{countryId:&quot;67&quot;,
countryName:&quot;us&quot;
},
{...}
]
}

*

There is no need of CountryRegion table but working with legacy DB.

I have implemented :


package com.example.demo.model;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = &quot;country&quot;)
public class Country {
@Id
@Column(name = &quot;countryid&quot;)
private int countryId;
@Column(name = &quot;countryname&quot;)
private String countryName;
@OneToMany(fetch = FetchType.EAGER, mappedBy = &quot;country&quot;)
private List&lt;CountryRegion&gt; regions = new ArrayList&lt;&gt;();
public int getCountryId() {
return countryId;
}
public void setCountryId(int countryId) {
this.countryId = countryId;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public List&lt;CountryRegion&gt; getRegions() {
return regions;
}
public void setRegions(List&lt;CountryRegion&gt; regions) {
this.regions = regions;
}
}
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = &quot;region&quot;)
public class Region {
@Id
@Column(name = &quot;regionid&quot;)
private int regionId;
@Column(name = &quot;regionname&quot;)
private String regionName;
@OneToMany(mappedBy = &quot;region&quot;)
private List&lt;CountryRegion&gt; countries = new ArrayList&lt;&gt;();
public int getRegionId() {
return regionId;
}
public void setRegionId(int regionId) {
this.regionId = regionId;
}
public String getRegionName() {
return regionName;
}
public void setRegionName(String regionName) {
this.regionName = regionName;
}
public List&lt;CountryRegion&gt; getCountries() {
return countries;
}
public void setCountries(List&lt;CountryRegion&gt; countries) {
this.countries = countries;
}
}
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
@Entity
@Table(name = &quot;countryregion1&quot;)
public class CountryRegion implements Serializable {
@Id @ManyToOne
@JoinColumn(name = &quot;regionid&quot;, referencedColumnName = &quot;regionId&quot;)
private Region region;
@Id @ManyToOne
@JoinColumn(name = &quot;countryid&quot;, referencedColumnName = &quot;countryId&quot;)
private Country country;
public Region getRegion() {
return this.region;
}
public void setRegion(Region region) {
this.region = null;
}
public Country getCountry() {
return this.country;
}
public void setCountry(Country country) {
this.country = country;
}
}
package com.example.demo.dao;
import com.example.demo.model.Country;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CountryRepository extends CrudRepository&lt;Country, Integer&gt; {
@Override
List&lt;Country&gt; findAll();
}
package com.example.demo.dao;
import com.example.demo.model.Country;
import com.example.demo.model.Region;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface RegionRepository extends CrudRepository&lt;Region, Integer&gt; {
@Override
List&lt;Region&gt; findAll();
}
  • Controller and service to expose api to get data.

There is something wrong in code above as I only want to fetch list of countries(or Region in case country)

This code is causing a infinite loop in JSON. Tried Json Ignore etc. but in that case i am not getting any value in lists.

TIA !!

答案1

得分: 0

首先,您应该指定"Country"和"Region"之间的关系。我认为您不需要定义"CountryRegion"类。如果关系是多对多的,您可以在"Region"类中使用以下代码:

@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
    name = "Employee_Project", 
    joinColumns = { @JoinColumn(name = "regionid") }, 
    inverseJoinColumns = { @JoinColumn(name = "countryid") }
)
Set<Country> countries = new HashSet<>();

如果是一对多的关系,您在"Region"类中实现的关系就足够了。但我认为您希望实现与您的愿望相对应的多对多关系。

英文:

first of all you should specify the relation between Country and Region. I think you dont need to define CountryRegion class.if the relation is ManyToMany then you can use below code in Region class :

@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
name = &quot;Employee_Project&quot;, 
joinColumns = { @JoinColumn(name = &quot;regionid&quot;) }, 
inverseJoinColumns = { @JoinColumn(name = &quot;countryid&quot;) }
)
Set&lt;Country &gt; countries = new HashSet&lt;&gt;();

and if it is OneToMany the raltion that you implement in Region class is enough. but i think you want ManyToMany corresponding to your wish

huangapple
  • 本文由 发表于 2020年10月10日 00:23:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/64283836.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定