gpt4 book ai didi

java - Spring Boot 数据存储库上的复合主外键

转载 作者:行者123 更新时间:2023-12-01 16:31:49 24 4
gpt4 key购买 nike

我正在尝试在两个实体之间建立关系,即订阅交付。两个实体都应使用用户的 id 作为主键(即,两者都与 User 处于一对一关系,但 Delivery 仅使用也为用户的 id存在于订阅中)。 Delivery 还使用属性 email 作为附加键(与用户 ID 一起建立复合主键)。虽然我用作 spring boot 的 jpa 后端的 eclipselink 似乎适合此定义,但在包含 jpa 存储库并显示以下错误消息时,我的应用程序崩溃了。

错误消息:

Caused by: java.lang.IllegalArgumentException: Expected id attribute type [class com.tnt.entity.Subscription$DeliveryPK] on the existing id attribute [SingularAttributeImpl[EntityTypeImpl@482885994:Subscription [ javaType: class com.tnt.entity.Subscription descriptor: RelationalDescriptor(com.tnt.entity.Subscription --> [DatabaseTable(tbl_subscription)]), mappings: 6],org.eclipse.persistence.mappings.ManyToOneMapping[subscription]]] on the identifiable type [EntityTypeImpl@1615668218:Delivery [ javaType: class com.tnt.entity.Subscription$Delivery descriptor: RelationalDescriptor(com.tnt.entity.Subscription$Delivery --> [DatabaseTable(tbl_subscription_delivery)]), mappings: 2]] but found attribute type [class com.tnt.entity.Subscription].
at org.eclipse.persistence.internal.jpa.metamodel.IdentifiableTypeImpl.getId(IdentifiableTypeImpl.java:204) ~[org.eclipse.persistence.jpa-2.7.0.jar:na]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation$IdMetadata.<init>(JpaMetamodelEntityInformation.java:262) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:88) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:211) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:161) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:144) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:69) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:312) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:212) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.util.Lazy.get(Lazy.java:94) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:121) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
... 88 common frames omitted

实体:

package com.tnt.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;

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

@Entity
@Table(name = "tbl_subscription")
public class Subscription {
@Column(name = "user_id")
@Id
private Long id;

@Column(name = "daily_report")
@Basic
private boolean receiveDailyReport;

@Column(name = "weekly_report")
@Basic
private boolean receiveWeeklyReport;

@Column(name = "monthly_report")
@Basic
private boolean receiveMonthlyReport;

@Column(name = "multi_report")
@Basic
private boolean multiReport;

@PrimaryKeyJoinColumn(name = "user_id")
@OneToOne(optional = false)
@JsonIgnore
private User user;

public Subscription() {

}

public Subscription(User user){
this.user = user;
this.receiveDailyReport = true;
}

@Entity
@Table(name = "tbl_subscription_delivery")
@IdClass(DeliveryPK.class)
public static class Delivery {
@JoinColumn(name = "subscription_id")
@ManyToOne
@Id
private Subscription subscription;

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

public Delivery() {

}

public Delivery(Subscription subscription, String email){
this.subscription = subscription;
this.email = email;
}

public Subscription getSubscription() {
return subscription;
}

public void setSubscription(Subscription subscription) {
this.subscription = subscription;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

// ... equals, hashCode
}

public static class DeliveryPK implements Serializable {

private Long subscription;

private String email;

public DeliveryPK() {
}

public Long getSubscription() {
return subscription;
}

public void setSubscription(Long subscription) {
this.subscription = subscription;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

// ... equals, hashCode
}

// ... getter, setter, equals, hashCode
}

存储库接口(interface):

interface DeliveryRepository : JpaRepository<Delivery, DeliveryPK> {
@Query("SELECT d FROM Delivery d WHERE d.subscription = :subscription AND d.email = :email")
fun findByEmail(subscription: Subscription, email: String): Optional<Delivery>
}

有人知道我做错了什么吗?

编辑:这个问题也可以用不同的方式提出 - 如果我用 SQL 对此进行建模,它可能看起来像这样:

CREATE TABLE tbl_user (
id BIGINT NOT NULL PRIMARY KEY,
email VARCHAR(255) UNIQUE,
password VARCHAR(255),
salt VARCHAR(64)
);

CREATE TABLE tbl_subscription (
user_id BIGINT NOT NULL REFERENCES tbl_user(id),
daily_report BOOLEAN,
weekly_report BOOLEAN,
monthly_report BOOLEAN,
multi_report BOOLEAN,
PRIMARY KEY (user_id)
);

CREATE TABLE tbl_subscription_delivery (
subscription_id BIGINT NOT NULL REFERENCES tbl_subscription(user_id),
email VARCHAR(255),
PRIMARY KEY(email, subscription_id)
);

如何在 JPA 2.0 中建模这种行为?

最佳答案

您可以使用单个主键关系属性映射订阅:

@Entity
@Table(name = "tbl_subscription")
public class Subscription {
@Id
@OneToOne(optional = false)
@JoinColumn(name = "user_id")
private User user;

@Column(name = "daily_report")
@Basic
private boolean receiveDailyReport;

@Column(name = "weekly_report")
@Basic
private boolean receiveWeeklyReport;

@Column(name = "monthly_report")
@Basic
private boolean receiveMonthlyReport;

@Column(name = "multi_report")
@Basic
private boolean multiReport;
...

或者,您可以使用 @MapsId 映射 Subscription (希望这与您在上面的评论中已经尝试过的内容不完全相同:) ):

@Entity
@Table(name = "tbl_subscription")
public class Subscription {
@Id
private Long id;

@OneToOne
@JoinColumn(name = "user_id")
@MapsId
private User user;

@Column(name = "daily_report")
@Basic
private boolean receiveDailyReport;

@Column(name = "weekly_report")
@Basic
private boolean receiveWeeklyReport;

@Column(name = "monthly_report")
@Basic
private boolean receiveMonthlyReport;

@Column(name = "multi_report")
@Basic
private boolean multiReport;
...

关于java - Spring Boot 数据存储库上的复合主外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62023911/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com