java - 使用抽象父类(super class)作为 Spring 数据存储库的参数

标签 java spring jpa spring-data-jpa

我知道如何实现spring数据仓库,

创建一个这样的界面:

public interface CountryRepository extends CrudRepository<Country, Long> {}

现在 Country 是一个 AbstractCatalog 并且我的项目中有(很多)更多目录。
我想知道我是否只能制作一个适用于所有目录的存储库:

public interface AbstractCatalogRepository extends CrudRepository<AbstractCatalog, Long> {}

现在我在保存时没有发现问题,但是如果我想搜索 AbstractCatalog 我已经确定我会碰壁,因为存储库不会知道哪个子它必须选择的类。

AbstractCatalog.class

@MappedSuperclass
public abstract class AbstractCatalog extends PersistentEntity {

    /**
     * The Constant serialVersionUID.
     */
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    /**
     * The code.
     */
    @Column(unique = true, nullable = false, updatable = false)
    private String code;
    /**
     * The description.
     */
    @Column(nullable = false)
    private String description;
    /**
     * The in use.
     */
    @Column(name = "IN_USE", nullable = false, columnDefinition = "bit default 1")
    private Boolean inUse = Boolean.TRUE;

    // getters and setters
}

Country.class

@Entity
@Table(name = "tc_country")
@AttributeOverrides({
    @AttributeOverride(name = "id", column =
            @Column(name = "COUNTRY_SID")),
    @AttributeOverride(name = "code", column =
            @Column(name = "COUNTRY_CODE")),
    @AttributeOverride(name = "description", column =
            @Column(name = "COUNTRY_DESCRIPTION"))})
public class Country extends AbstractCatalog {

    public static final int MAX_CODE_LENGTH = 11;

    @Column(name = "GEONAMEID", nullable = true, unique = false)
    private Long geonameid;

    // getter and setter
}

有没有人知道,我如何可以只为 AbstractCatalog 类的所有实现使用一个存储库,而不必一遍又一遍地创建相同的接口(interface),而名称和其他属性的差异最小?

最佳答案

如果您没有在数据库端使用表继承(例如带有 descriminator column 的父类(super class)表),AFAIK 并基于阅读 JPA tutorial ,这是无法做到的(即简单地为您的抽象类使用 @MappedSuperclass 注释)

Mapped superclasses cannot be queried and cannot be used in EntityManager or Query operations. You must use entity subclasses of the mapped superclass in EntityManager or Query operations. Mapped superclasses can't be targets of entity relationships

注意,JPA 存储库抽象在底层使用 EntityManager。我做了一个简单的测试,你会得到(在 Hibernate 实现的情况下)一个“IllegalArgumentException : not an entity AbstractClass

另一方面,如果你确实使用表继承,那么你可以使用抽象类型。我知道你说“只有最小的改变”(我想我的简短回答是我认为不可能 - 可能是因为你猜到的原因),所以我猜这个答案的其余部分适用于其他好奇的人;-)

表继承策略的一个例子是这样的(免责声明:这不是 erd 继承的 correct visualization,但 MySQL Workbench 不支持它,但我在下面将模型转发到 MYSQL它需要的方式)

enter image description here

其中 CountryCatalog 具有对 AbstractCatalog 表 pk (id) 的 FK/PK 引用。 AbstractCatalog 表有一个 descriminatorColumn 将用于确定父类(super class)型的出现与哪个子类型相关。

就你如何编码而言,它看起来像

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="descriminatorColumn")
@Table(name="AbstractCatalog")
public abstract class AbstractCatalog {
    @Id
    private long id;
    ...
}

@Entity
@Table(name = "CountryCatalog")
public class CountryCatalog extends AbstractCatalog {
    // id is inherited
    ...
}

public interface AbstractCatalogRepository 
                 extends JpaRepository<AbstractCatalog, Long> {

}

@Repository
public class CountryCatalogServiceImpl implements CountryCatalogService {

    @Autowired
    private AbstractCatalogRepository catalogRepository;

    @Override
    public List<CountryCatalog> findAll() {
        return (List<CountryCatalog>)(List<?>)catalogRepository.findAll();
    }

    @Override
    public CountryCatalog findOne(long id) {
        return (CountryCatalog)catalogRepository.findOne(id);
    }   
}

基本上,总而言之,如果您没有表继承,那么您尝试做的事情将不起作用。存储库的类类型需要是实体。如果您的表没有以这种方式设置以进行继承,则归结为您是否要更改表。不过,避免多个存储库可能有点过分。

我使用的一些引用文献是 herehere

注意:此答案中的所有内容均针对 Hibernate 提供程序进行了测试

关于java - 使用抽象父类(super class)作为 Spring 数据存储库的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25237664/

相关文章:

spring - Spring Data REST 的 QueryDSL 集成可以用来执行更复杂的查询吗?

Java:使用代码模型生成具有默认值的注释

java - 名称 [资源] 未在此上下文中绑定(bind)。找不到 [jdbc]

java.lang.NoClassDefFoundError : org/hibernate/cache/spi/RegionFactory - When upgrading from spring 3 to spring 4 错误

Spring ContentNegotiatingViewResolver - 如何使用 jsp View 的 bean 名称而不是带有路径参数的完整 url

java - Spring API 请求在生产环境中比在本地主机上花费更长的时间(相同的数据)

java - 寻找与 JPA 模型交互的通用库

java - 如何仅更新字段的子集并更新存储库?

java - 具有相同方法的多个 Java 8 枚举

Java:重命名从远程服务器下载的文件