Java 使用抽象超类作为Spring数据存储库的参数
我知道如何实现spring数据存储库 创建如下界面:Java 使用抽象超类作为Spring数据存储库的参数,java,spring,jpa,spring-data-jpa,Java,Spring,Jpa,Spring Data Jpa,我知道如何实现spring数据存储库 创建如下界面: public interface CountryRepository extends CrudRepository<Country, Long> {} 现在我在保存时没有看到问题,但是如果我想搜索抽象目录,我已经确定我会遇到麻烦,因为存储库不知道它必须选择哪个子类 抽象目录类 国家级 有没有人知道,我如何能够只使用一个存储库来实现AbstractCatalog类的所有实现,而不必一次又一次地创建相同的接口,并且在名称和其他属性上
public interface CountryRepository extends CrudRepository<Country, Long> {}
现在我在保存时没有看到问题,但是如果我想搜索抽象目录
,我已经确定我会遇到麻烦,因为存储库不知道它必须选择哪个子类
抽象目录类
国家级
有没有人知道,我如何能够只使用一个存储库来实现AbstractCatalog
类的所有实现,而不必一次又一次地创建相同的接口,并且在名称和其他属性上的差异最小?您使用的数据库是什么
如果是JPA,请看
如果是Mongo,则需要正确调整配置
因此,这是可能的。如果您没有在数据库端使用表继承(例如,带的超类表),AFAIK,并且基于读取,这是无法做到的(即,仅对抽象类使用
@MappedSuperclass
注释)
无法查询映射的超类,并且不能在EntityManager或查询操作中使用。必须在EntityManager或查询操作中使用映射超类的实体子类。映射的超类不能是实体关系的目标
注意,JPA存储库抽象在引擎盖下使用EntityManager。我做了一个简单的测试,在Hibernate实现的情况下,您将得到一个“IllegalArgumentException:不是实体抽象类”
”
另一方面,如果使用表继承,则可以使用抽象类型。我知道你说的是“只要一点点改变”(我猜我的简短回答是我不认为这是可能的——可能是因为你猜的原因),所以我猜这个答案的其余部分是给其他好奇的人的;-)
表继承策略的一个示例如下(免责声明:这不是for erd继承,但MySQL Workbench不支持它,但我下面介绍的是按照需要将模型向前工程到MySQL)
其中CountryCatalog
对AbstractCatalog
表PK(id)有一个FK/PK引用。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);
}
}
@实体
@继承(策略=InheritanceType.JOINED)
@鉴别器列(name=“descriminatorColumn”)
@表(name=“AbstractCatalog”)
公共抽象类抽象目录{
@身份证
私人长id;
...
}
@实体
@表(name=“CountryCatalog”)
公共类CountryCatalog扩展了AbstractCatalog{
//id是继承的
...
}
公共接口目录库
扩展JpaRepository和
注意:此答案中的所有内容都是针对Hibernate提供程序进行测试的Oke,新项目,我将稍微关注一下此设置。
问题是:
我们想添加附件,但附件可以上载文件、链接或邮件。
Pojo课程:
附件.java:
FileAttachment.java:
MailAttachment.java:
LinkAttachment.java:
Spring数据回购:
AttachmentRepository.java:
public interface AttachmentRepository扩展了CustomRepository{
列出findByTask(任务);
}
CustomRepository.java:
公共接口CustomRepository扩展
分页和排序存储库,
JpaSpecificationExecutor,
QueryDSL谓词执行器{
@凌驾
列出findAll();
}
最后是服务:
@Service
public class AttachmentServiceImpl implements AttachmentService {
@Inject
private AttachmentRepository attachmentRepository;
@Override
public List<Attachment> findByTask(Task task) {
return attachmentRepository.findByTask(task);
}
@Override
@Transactional
public Attachment save(Attachment attachment) {
return attachmentRepository.save(attachment);
}
}
@服务
公共类AttachmentServiceImpl实现AttachmentService{
@注入
私人附庸;私人附庸;
@凌驾
公共列表findByTask(任务){
返回attachmentRepository.findByTask(任务);
}
@凌驾
@交易的
公共附件保存(附件附件){
返回附件保存(附件);
}
}
这将导致:
我可以用我创建的任何实现保存到抽象回购,JPA将正确执行。
如果我调用findByTask(Task Task)
我会得到所有子类的列表
,它们后面有正确的子类。
这意味着,您可以创建一个执行instanceof
的渲染器,并且可以为每个子类自定义渲染
缺点是,您仍然需要创建自定义的特定存储库,但仅当您想要查询子类中的特定属性时,或者当您只想要一个特定实现而不是所有实现时。对于@heritation
=>没有为实体指定标识符:Country。
对于@MappedSuperClass
=>java.lang.IllegalArgumentException:无法为方法public abstract be.model.AbstractCatalog创建查询元模型我认为“@Inheritation”中的问题在于“@AttributeOverride”,请尝试在Country中显式声明“@Id”列我有点不知所措,当@Id位于抽象目录中时,我如何在country中添加它?或者我必须将getter/setter更改为抽象方法并将变量移动到实现中吗?谢谢你的回答,我刚刚编辑了这个问题并提供了Pojo的代码。我朝这个方向思考的原因=>我在gui中有一个自定义组件,它适用于所有目录。现在我正在搜索的是手中的repo,如果它们都有相同的repo,它将简化映射程序。使用@MappedSuperclass
是不可能的。实体需要由具体类查询,正如我在链接中提到的。作为参数传递的类型是将被查询的类。无法查询映射的超类
@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
}
@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);
}
}
@Entity
@Table(name = "T_ATTACHMENT")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING)
public abstract class Attachment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ATTACHMENT_SID")
private Long id;
@ManyToOne
@JoinColumn(name = "TASK_SID", referencedColumnName = "TASK_SID", nullable = false, unique = false, insertable = true, updatable = true)
private Task task;
@ManyToOne
@JoinColumn(name = "USER_SID", referencedColumnName = "USER_SID", nullable = false, unique = false, insertable = true, updatable = true)
private User user;
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
@Entity
@Table(name = "T_FILE_ATTACHMENT")
@DiscriminatorValue("FILE")
public class FileAttachment extends Attachment {
@Column(name = "NAME", nullable = false, unique = false)
private String fileName;
@Lob
@Basic
@Column(name = "FILE", nullable = false, unique = false)
private byte[] file;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public byte[] getFile() {
return file;
}
public void setFile(byte[] file) {
this.file = file;
}
}
@Entity
@Table(name = "T_MAIL_ATTACHMENT")
@DiscriminatorValue("MAIL")
public class MailAttachment extends Attachment {
@Column(name = "RECIPIENT", nullable = false, unique = false)
private String to;
@Column(name = "CC", nullable = true, unique = false)
private String cc;
@Column(name = "BCC", nullable = true, unique = false)
private String bcc;
@Column(name = "TITLE", nullable = true, unique = false)
private String title;
@Column(name = "MESSAGE", nullable = true, unique = false)
private String message;
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getCc() {
return cc;
}
public void setCc(String cc) {
this.cc = cc;
}
public String getBcc() {
return bcc;
}
public void setBcc(String bcc) {
this.bcc = bcc;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
@Entity
@Table(name = "T_LINK_ATTACHMENT")
@DiscriminatorValue("LINK")
public class LinkAttachment extends Attachment {
@Column(name = "DESCRIPTION", nullable = true, unique = false)
private String description;
@Column(name = "LINK", nullable = false, unique = false)
private String link;
public String getDescription() {
return description == null ? getLink() : description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
public interface AttachmentRepository extends CustomRepository<Attachment, Long> {
List<Attachment> findByTask(Task task);
}
public interface CustomRepository<E, PK extends Serializable> extends
PagingAndSortingRepository<E, PK>,
JpaSpecificationExecutor<E>,
QueryDslPredicateExecutor<E> {
@Override
List<E> findAll();
}
@Service
public class AttachmentServiceImpl implements AttachmentService {
@Inject
private AttachmentRepository attachmentRepository;
@Override
public List<Attachment> findByTask(Task task) {
return attachmentRepository.findByTask(task);
}
@Override
@Transactional
public Attachment save(Attachment attachment) {
return attachmentRepository.save(attachment);
}
}