我知道如何实现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它需要的方式)
其中 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);
}
}
基本上,总而言之,如果您没有表继承,那么您尝试做的事情将不起作用。存储库的类类型需要是实体。如果您的表没有以这种方式设置以进行继承,则归结为您是否要更改表。不过,避免多个存储库可能有点过分。
注意:此答案中的所有内容均针对 Hibernate 提供程序进行了测试
关于java - 使用抽象父类(super class)作为 Spring 数据存储库的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25237664/