使用抽象超类作为Spring数据存储库的参数

2024-02-21

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

创建一个像这样的界面:

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

Now Country is an AbstractCatalog我的项目中有(很多)更多目录。
我想知道是否可以只创建一个适用于所有目录的存储库:

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

现在我在保存时没有看到问题,但如果我想搜索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
}

国家级

@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类而不必一遍又一遍地创建相同的接口,并且名称和其他属性的差异最小?


如果您没有在数据库端使用表继承(例如带有鉴别器列 http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Example_single_table_inheritance_table_in_database),据我所知,并基于阅读JPA教程 http://docs.oracle.com/javaee/7/tutorial/doc/persistence-intro002.htm#BNBQN,这是无法完成的(即简单地使用@MappedSuperclass抽象类的注释)

映射的超类无法查询,也不能在 EntityManager 或查询操作中使用。您必须在 EntityManager 或查询操作中使用映射超类的实体子类。映射的超类不能成为实体关系的目标

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

另一方面,如果你do使用表继承,那么你can使用抽象类型。我知道你说过“只需做出最小的改变”(我想我的简短回答是我认为这是不可能的 - 可能是出于你猜测的原因),所以我想这个答案的其余部分是为了其他好奇的头脑;-)

表继承策略的一个示例如下(免责声明:这不是正确的观想 http://andrewbelson.wordpress.com/2012/12/05/generalizationinheritance-when-er-modelling-using-crows-feet-notation/对于 erd 继承,但 MySQL Workbench 不支持它,但我在下面将模型按照需要的方式正向设计为 MYSQL)

Where CountryCatalog有 FK/PK 参考AbstractCatalog表 pk (id)。这AbstractCatalog表有一个descriminatorColumn将用于确定超类型出现与哪个子类型相关。

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

@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);
    }   
}

基本上,总而言之,如果没有表继承,您尝试做的事情将不起作用。存储库的类类型必须是实体。如果您的表没有以这种方式设置继承,那么它就取决于您是否要更改表。不过,仅仅为了避免多个存储库可能有点过分。

我使用的一些参考是here http://docs.oracle.com/javaee/7/tutorial/doc/persistence-intro002.htm#BNBQN and here http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Example_single_table_inheritance_table_in_database

Note:这个答案中的所有内容都针对 Hibernate 提供程序进行了测试

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用抽象超类作为Spring数据存储库的参数 的相关文章

随机推荐