@MappedSuperclass 被分配给@OneToMany spring-data

问题描述 投票:0回答:1

我正在开发一个应用程序来跟踪客户帐户。每个客户可以有多个帐户。 挑战在于帐户对象是多态的。 有一个抽象类

Account
有 2-3 个方法,然后目前有 2 个子类型
SavingsAccount
CreditAccount

我尝试的是让

Account
对象使用
@MappedSuperclass
注释,然后每个具体类照常具有
@Entity
注释。

问题似乎是映射我的客户对象

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name="customer_id", referencedColumnName = "id")
    List<Account> accounts = new ArrayList<>();

当我使用它时,我在 IDE 中收到来自 Spring 的警告,但在运行时我收到此错误。

com.example.models.Customer.accounts' targets the type 'com.example.models.Account' which is not an '@Entity' type

是否没有办法针对多态对象列表进行 @OneToMany 映射?即使它们存储在同一个表中?

spring-data-jpa spring-data
1个回答
0
投票

您收到的错误与预期一致。您需要使用

@Inheritance
注释您的基本 Account 类。如果使用单个表,Account 类可能如下所示:

import jakarta.persistence.*;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "account_type")
public abstract class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "customer_id", nullable = false)
    private Customer customer;

    // getters and setters
}

你的子类将如下所示

import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;

@Entity
@DiscriminatorValue("SAVINGS")
public class SavingsAccount extends Account {
}

@Entity
@DiscriminatorValue("CREDIT")
public class CreditAccount extends Account {
}

我用这个客户实现验证了上述代码:

import jakarta.persistence.*;

import java.util.ArrayList;
import java.util.List;

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "customer_id")
    private List<Account> accounts = new ArrayList<>();

    public void addAccount(Account account) {
        account.setCustomer(this);
        accounts.add(account);
    }

    // getters/setters
}

客户存储库

import org.springframework.data.repository.CrudRepository;

public interface CustomerRepository extends CrudRepository<Customer, Long> {
}

迁徙路线

CREATE TABLE customer
(
    id SERIAL PRIMARY KEY
);

CREATE TABLE account
(
    id           SERIAL PRIMARY KEY,
    account_type VARCHAR(16) NOT NULL,
    customer_id  INT         NOT NULL,
    CONSTRAINT fk_customer FOREIGN KEY (customer_id) REFERENCES customer (id)
);

PostgresTestContainerConfig

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;

@TestConfiguration
public class PostgresTestContainerConfig {

    @Bean
    @ServiceConnection
    public PostgreSQLContainer<?> postgreSQLContainer() {
        return new PostgreSQLContainer<>("postgres:15-alpine");
    }
}

测试

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.context.annotation.Import;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
@AutoConfigureTestDatabase
@Import(no.vicx.database.PostgresTestContainerConfig.class)
class CustomerRepositoryTest {

    @Autowired
    TestEntityManager entityManager;

    @Autowired
    CustomerRepository sut;

    @Test
    void testInserts() {
        Customer customer = new Customer();
        customer.addAccount(new SavingsAccount());
        customer.addAccount(new CreditAccount());

        sut.save(customer);

        assertEquals(2, getAccountCountInDb());

        var customerInDb = entityManager.find(Customer.class, customer.getId());

        assertInstanceOf(SavingsAccount.class, customerInDb.getAccounts().getFirst());
        assertInstanceOf(CreditAccount.class, customerInDb.getAccounts().getLast());
    }

    long getAccountCountInDb() {
        return (long) entityManager.getEntityManager()
                .createQuery("SELECT COUNT(1) FROM Account ")
                .getSingleResult();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.