Spring JPA多对多关系无法获取数据
我一直在用Spring开发一个应用程序,我正在使用JPA来处理数据库。我有两个实体,他们是如下Spring JPA多对多关系无法获取数据
合伙实体
@Entity
public class Partner {
@ManyToMany()
private List<Tenant> tenants;
public List<Tenant> getTenants() {
return tenants;
}
public void setTenants(List<Tenant> tenants) {
this.tenants = tenants;
}
}
租客实体
@Entity
public class Tenant {
...
}
这两个实体已经被PartnerService
和TenantService
服务暴露出来。
在另一个服务类中,我从PartnerService
中检索合作伙伴,当我调用partner.getTenants()
时,它返回一个包含0个元素的列表。但在特定合作伙伴有2个租户的数据库中。我的服务类是如下
@Service
public class DBOutboundInjector implements OutboundInjector {
private final ApplicationContext context;
@Autowired
public DBOutboundInjector(ApplicationContext context) {
this.context = context;
}
@Override
@Transactional
public boolean insertEntry(Long partnerId) {
PartnerService partnerService = context.getBean(PartnerService.class);
Partner partner = partnerService.getPartnerById(partnerId);
List<Tenant> partnerTenants = partner.getTenants();
...
}
}
请参考以下方案
选择1:尝试使用@ManyToMany FetchType.EAGER
@Entity
public class Partner {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
public Partner() {
}
public Partner(String name, String location, List<Tenant> tentans) {
this.name = name;
this.location = location;
this.tenants = tentans;
}
@ManyToMany(fetch = FetchType.EAGER)
private List<Tenant> tenants;
替代2:PartnerRepository添加新的方法来获取合作伙伴并提取相关的租户对象列表。
@Repository
public interface PartnerRepository extends JpaRepository<Partner,Long> {
@Query("SELECT p FROM Partner p JOIN FETCH p.tenants WHERE p.id=(:id)")
public Partner findByIdFetchTenant(@Param("id") Long id);
这是例行如何让租户列表,可以自动装配在仓库里,你ParentServcie
partner = partnerRepository.findByIdFetchTenant(partner.getId());
System.out.println("One Partner" + partner);
System.out.println(partner.getTenants());
编辑
我分享完整的示例,在这种情况下,进出口使用spring boot,web,h2数据库,spring jpa
application.properties
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.url:jdbc:h2:mem:~/test
Partner.class
@Entity
public class Partner {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
public Partner() {
}
public Partner(String name, String location, List<Tenant> tentans) {
this.name = name;
this.location = location;
this.tenants = tentans;
}
@ManyToMany(fetch = FetchType.EAGER)
private List<Tenant> tenants;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
private String name;
private String location;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public List<Tenant> getTenants() {
return tenants;
}
public void setTenants(List<Tenant> tenants) {
this.tenants = tenants;
}
@Override
public String toString() {
return "Partner{" +
"id=" + id +
", name='" + name + '\'' +
", location='" + location + '\'' +
'}';
}
}
Tenant.class
@Entity
public class Tenant {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
public Tenant() {
}
@Override
public String toString() {
return "Tenant{" +
"id=" + id +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
public Tenant(String name, String description) {
this.name = name;
this.description = description;
}
private String name;
private String description;
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 String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
PartnerRepository.class
@Repository
public interface PartnerRepository extends JpaRepository<Partner,Long> {
@Query("SELECT p FROM Partner p JOIN FETCH p.tenants WHERE p.id=(:id)")
public Partner findByIdFetchTenant(@Param("id") Long id);
}
TenantRepository.class
@Repository
public interface TenantRepository extends JpaRepository<Tenant,Long> {
}
个
MyApp.class的
@SpringBootApplication
public class MyApp {
private static final Logger logger = LoggerFactory.getLogger(MyApp.class);
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
@Bean
public CommandLineRunner runner(TenantRepository tenantRepository, PartnerRepository partnerRepository){
return (args) -> {
logger.info("Creating Data Many to Many...");
Tenant tenant1,tenant2,tenant3 = null;
Partner partner=null;
tenant1 = new Tenant("tenant1","tenant1");
tenant2 = new Tenant("tenant2","tenant2");
tenant3 = new Tenant("tenant3","tenant3");
tenantRepository.save(tenant1);
tenantRepository.save(tenant2);
tenantRepository.save(tenant3);
partner = new Partner("partner1","partner location", Arrays.asList(tenant1,tenant2,tenant3));
partnerRepository.save(partner);
partner = partnerRepository.findByIdFetchTenant(partner.getId());
System.out.println("One Partner" + partner);
System.out.println(partner.getTenants());
};}}
的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.boot.spring</groupId>
<artifactId>myjpademo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>myjpademo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
问候。
只要按照示例吹。学生和学科之间存在着多种多样的关系。
@Entity
public class Student{
private int id;
private String name;
private Set<Subject> subjects;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "student_subject", joinColumns = @JoinColumn(name = "student_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "subject_id", referencedColumnName = "id"))
public Set<Subject> getSubjects() {
return subjects;
}
public void setSubjects(Set<Subject> subjects) {
this.subjects = subjects;
}
}
和
@Entity
public class Subject {
private int id;
private String name;
private Set<Student> students;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
@ManyToMany(mappedBy = "subjects")
public Set<Student> getStudents() {
return students;
}
}
感谢您的回复,但这也不起作用。也许问题出在我得到'PartnerService' bean的方式。 – rnavagamuwa
设置实测此'取= FetchType.EAGER'给出相同的结果。当我做第二个建议时,它甚至不会退还合作伙伴。看起来像自定义查询没有执行。 – rnavagamuwa