chi*_*rld 20 java spring jpa spring-data-jpa
我知道spring数据存储库的实现:
创建一个这样的界面:
public interface CountryRepository extends CrudRepository<Country, Long> {}
Run Code Online (Sandbox Code Playgroud)
现在Country是一个AbstractCatalog,我在矿山项目中有很多(很多)目录.
我想知道我是否可以创建一个适用于所有目录的存储库:
public interface AbstractCatalogRepository extends CrudRepository<AbstractCatalog, Long> {}
Run Code Online (Sandbox Code Playgroud)
现在有了保存,我没有直接看到一个问题,但如果我想搜索一个AbstractCatalog我已经确定我会碰壁,因为回购将不知道他必须选择什么对象.
@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
}
Run Code Online (Sandbox Code Playgroud)
@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
}
Run Code Online (Sandbox Code Playgroud)
有没有人知道如何只AbstractCatalog为名称和实现类的最小变化一次又一次地创建相同的接口,为所有实现做出1回购?
Pau*_*tha 14
如果您没有在数据库端使用表继承(例如,具有descriminator列的超类表),AFAIK,并且基于阅读JPA教程,则无法完成此操作(即只使用@MappedSuperclass抽象类的注释)
无法查询映射的超类,也无法在EntityManager或Query操作中使用.您必须在EntityManager或Query操作中使用映射的超类的实体子类.映射的超类不能成为实体关系的目标
注意,JPA存储库抽象使用了一个EntityManager.我做了一个简单的测试,你会得到什么(在Hibernate实现的情况下)IllegalArgumentException : not an entity AbstractClass"
在另一方面,如果你做使用表继承,那么你可以使用抽象类型.我知道你说"只做了极小的改变"(我想我的简短回答是我不认为这是可能的 - 可能是因为你猜对了的原因),所以我猜这个答案的其余部分是针对其他探究的思想; - )
表继承策略的一个例子是这样的(免责声明:这不是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);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,总而言之,如果您没有表继承,那么您尝试执行的操作将无法正常工作.存储库的类类型需要是实体.如果您的表没有以这种方式设置继承,那么它只取决于您是否要更改表.但是,避免多个存储库可能有点多.
注意:此答案中的所有内容都是针对Hibernate提供程序进行测试的
好的,新项目,我将对此进行一些设置。
问题是:我们想添加附件,但是附件可以上传文件,链接或邮件。
Pojo课程:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
Spring数据仓库:
public interface AttachmentRepository extends CustomRepository<Attachment, Long> {
List<Attachment> findByTask(Task task);
}
Run Code Online (Sandbox Code Playgroud)
public interface CustomRepository<E, PK extends Serializable> extends
PagingAndSortingRepository<E, PK>,
JpaSpecificationExecutor<E>,
QueryDslPredicateExecutor<E> {
@Override
List<E> findAll();
}
Run Code Online (Sandbox Code Playgroud)
最后的服务:
@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);
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
我可以使用我创建的任何实现将其保存到抽象存储库中,JPA会正确执行。
如果我打电话给findByTask(Task task)我,我得到了List<Attachment>所有子类的一个,并且它们的后面都有正确的子类。
这意味着,您可以让一个渲染器来做,instanceof并且可以为每个子类自定义渲染。
缺点是,您仍然需要创建自定义的特定存储库,但是仅当您要查询特定属性时,才需要子类中的内容,或者仅需要1个特定实现而不是所有实现。
| 归档时间: |
|
| 查看次数: |
27499 次 |
| 最近记录: |