[SPRING] Spring 데이터 저장소에 대한 매개 변수로 추상 수퍼 클래스 사용
SPRINGSpring 데이터 저장소에 대한 매개 변수로 추상 수퍼 클래스 사용
스프링 데이터 저장소의 구현을 알고 :
다음과 같은 인터페이스를 작성하십시오.
public interface CountryRepository extends CrudRepository<Country, Long> {}
Now Country는 AbstractCatalog이고 저는 광산 프로젝트에 카탈로그를 많이 보유하고 있습니다. 모든 카탈로그에서 작동해야하는 저장소를 만들 수 있는지 궁금합니다.
public interface AbstractCatalogRepository extends CrudRepository<AbstractCatalog, Long> {}
이제 save를 사용하면 문제가 직접적으로 나타나지 않지만 Abstract Catalog를 검색하려면 repo가 어떤 객체를 선택해야하는지 알 수 없으므로 벽을 치게 될 것입니다.
@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의 모든 구현에 대해 이름과 구현 클래스의 최소한의 변경으로 동일한 인터페이스를 반복해서 만들지 않고도 1 Repo를 만들 수있는 아이디어가 있습니까?
해결법
-
==============================
1.데이터베이스 측에서 테이블 상속 (예 : descriminator 열이있는 수퍼 클래스 테이블), AFAIK를 사용하지 않고 JPA 튜토리얼을 읽지 않는 경우 (즉, 추상 클래스에 @MappedSuperclass 주석을 사용하는 것)
데이터베이스 측에서 테이블 상속 (예 : descriminator 열이있는 수퍼 클래스 테이블), AFAIK를 사용하지 않고 JPA 튜토리얼을 읽지 않는 경우 (즉, 추상 클래스에 @MappedSuperclass 주석을 사용하는 것)
JPA 저장소 추상화는 내부적으로 EntityManager를 사용합니다. 나는 간단한 테스트를 수행했고 (Hibernate 구현의 경우) "IllegalArgumentException : 엔터티가 아닌 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); } }
결론적으로 결론적으로, 당신이 테이블 상속이 없다면 당신이하려고하는 것은 작동하지 않을 것입니다. 저장소의 클래스 유형은 엔티티 여야합니다. 테이블이 상속을 위해이 방법으로 설정되지 않은 경우에는 테이블을 변경할지 여부 만 결정됩니다. 그것은 단지 여러 저장소를 피하기 위해 조금은 다를 수 있습니다.
내가 사용한 몇 가지 참고 자료는 여기와 여기에 있습니다.
참고 :이 대답의 모든 것은 최대 절전 모드 공급자에 대해 테스트됩니다.
-
==============================
2.Oke, 새로운 프로젝트와 나는이 설정을 조금 따르고 있습니다. 문제는 : 첨부 파일을 추가하고 싶지만 첨부 파일은 파일, 링크 또는 메일을 업로드 할 수 있습니다.
Oke, 새로운 프로젝트와 나는이 설정을 조금 따르고 있습니다. 문제는 : 첨부 파일을 추가하고 싶지만 첨부 파일은 파일, 링크 또는 메일을 업로드 할 수 있습니다.
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; } }
@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); } }
결과는 다음과 같습니다.
내가 만든 모든 구현으로 추상적 인 저장소에 저장할 수 있습니다. JPA는이를 올바르게 수행합니다.
findByTask (Task task)를 호출하면 모든 서브 클래스의 List
가 생기고 뒤쪽에 올바른 서브 클래스가 생깁니다. 즉, instanceof를 수행하는 렌더러를 만들 수 있으며 각 하위 클래스의 렌더링을 사용자 정의 할 수 있습니다. 단점은 여전히 사용자 지정 저장소를 만들 필요가 있지만 하위 클래스에있는 특정 속성을 쿼리하거나 모든 구현 대신 특정 구현을 1 개만 원하는 경우에만 쿼리를 작성해야한다는 것입니다.
-
==============================
3.어떤 DB를 사용하고 있습니까?
어떤 DB를 사용하고 있습니까?
JPA 인 경우 다음을 확인하십시오. Spring Data JPA에서 MappedSuperClass의 모든 자식에 대해 일반적인 저장소를 사용할 수 있습니까?
Mongo라면 잭슨 다형성 구성을 적절하게 조정해야합니다. http://wiki.fasterxml.com/JacksonPolymorphicDeserialization
그래서 이것은 가능합니다.
from https://stackoverflow.com/questions/25237664/use-abstract-super-class-as-parameter-to-spring-data-repository by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 분리 된 엔터티가 지속 오류를 전달했습니다. (0) | 2019.01.03 |
---|---|
[SPRING] Feign 클라이언트 + Spring Cloud (Brixton RC2)에서 동적 값을 사용하여 @Headers 사용 (0) | 2019.01.03 |
[SPRING] Spring에서 RestTemplate 사용하기. 예외 - 확장 할 수있는 변수가 충분하지 않습니다. (0) | 2019.01.03 |
[SPRING] 모든 역할 이름에 스프링 보안 접두사 "ROLE_"이 추가 되었습니까? (0) | 2019.01.03 |
[SPRING] 최대 절전 모드 쿼리 사용 : 콜론은 매개 변수로 처리되거나 콜론은 이스케이프 처리됩니다. (0) | 2019.01.03 |