Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用抽象超类作为Spring数据存储库的参数_Java_Spring_Jpa_Spring Data Jpa - Fatal编程技术网

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

Java 使用抽象超类作为Spring数据存储库的参数,java,spring,jpa,spring-data-jpa,Java,Spring,Jpa,Spring Data Jpa,我知道如何实现spring数据存储库 创建如下界面: public interface CountryRepository extends CrudRepository<Country, Long> {} 现在我在保存时没有看到问题,但是如果我想搜索抽象目录,我已经确定我会遇到麻烦,因为存储库不知道它必须选择哪个子类 抽象目录类 国家级 有没有人知道,我如何能够只使用一个存储库来实现AbstractCatalog类的所有实现,而不必一次又一次地创建相同的接口,并且在名称和其他属性上

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

创建如下界面:

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