带有@DiscriminatorValue 的多个对象的单个存储库
Single repository for multiple objects with @DiscriminatorValue
我有几个实体共享同一个数据库 table 与 @DiscriminatorValue
和一个基地 class:
@Entity(name = "base_details")
@DiscriminatorColumn(name = "type")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Getter
@Setter
public abstract class BaseDetails {
@Id
@Column(name = "identifier")
private String identifier;
@Column(name = "item_type")
@Enumerated(EnumType.STRING)
private Type type;
}
@Entity
@DiscriminatorValue("ONE")
@Getter
@Setter
public class FirstDetails extends BaseDetails {
...
}
@Entity
@DiscriminatorValue("TWO")
@Getter
@Setter
public class SecondDetails extends BaseDetails {
...
}
这很好用,但我 运行 遇到了一个问题,因为有太多单独的存储库:
@Repository
public interface OneDetailsRepository extends JpaRepository<OneDetails, String> { ... }
等等
有没有办法拥有一个可以与所有派生实体一起使用的存储库(等式 BaseDetailsRepository
)?
编辑:
我正在寻找的是这样的东西:
@Repository
public interface BaseDetailsRepository extends JpaRepository<? extends BaseDetails, String> {
OneDetails findOne(String identifier);
SecondDetails findOne(String identifier);
}
@NoRepositoryBean // Read only repository
public interface BaseDetailsRepository<T extends BaseDetails>
extends JpaRepository<T, String> {
T findOne(String identifier);
T findOne(Long id);
Iterable<T> findAll();
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
并且您还可以为每个实体拥有三个存储库:
@Transactional
public interface BaseRepository extends BaseDetailsRepository<BaseDetails> { }
@Transactional
public interface FirstDetailsRepository extends BaseDetailsRepository<BaseDetails>,JpaRepository<T extends BaseDetails, String>{ }
@Transactional
public interface SecondDetailsRepository extends BaseDetailsRepository<BaseDetails>,JpaRepository<T extends BaseDetails, String> { }
您可以进行如下操作:
存储库:BaseDetailsRepo.java
@Repository
public interface BaseDetailsRepo extends JpaRepository<BaseDetails, String>{
//make the return according to you ..it shouldn't be list....
@Query("FROM SecondDetails AS bd WHERE bd.identifier=:identifier")
public List<SecondDetails> getSecondDetailsByIdentifier(@Param("identifier") String identifier);
@Query("FROM FirstDetails AS bd WHERE bd.identifier=:identifier")
public List<FirstDetails> getFirstDetailsByIdentifier(@Param("identifier") String identifier);
}
控制器:DemoController.java
@Controller
public class DemoController {
@Autowired
private BaseDetailsRepo baseDetailsRepo;
@GetMapping(value="/test")
public ResponseEntity test(){
FirstDetails fd = new FirstDetails();
fd.setIdentifier("fd1-demo");
FirstDetails fd1 = new FirstDetails();
fd1.setIdentifier("fd2-demo");
SecondDetails sd = new SecondDetails();
sd.setIdentifier("sd1-demo");
baseDetailsRepo.save(fd);
baseDetailsRepo.save(fd1);
baseDetailsRepo.save(sd);
return new ResponseEntity("Success",HttpStatus.OK);
}
@GetMapping(value="/test/second/{id}")
public ResponseEntity getSecondDetails(@PathVariable String id){
return new ResponseEntity(baseDetailsRepo.getSecondDetailsByIdentifier(id),HttpStatus.OK);
}
@GetMapping(value="/test/first/{id}")
public ResponseEntity getFirstDetails(@PathVariable String id){
return new ResponseEntity(baseDetailsRepo.getFirstDetailsByIdentifier(id),HttpStatus.OK);
}
}
输出
我有几个实体共享同一个数据库 table 与 @DiscriminatorValue
和一个基地 class:
@Entity(name = "base_details")
@DiscriminatorColumn(name = "type")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Getter
@Setter
public abstract class BaseDetails {
@Id
@Column(name = "identifier")
private String identifier;
@Column(name = "item_type")
@Enumerated(EnumType.STRING)
private Type type;
}
@Entity
@DiscriminatorValue("ONE")
@Getter
@Setter
public class FirstDetails extends BaseDetails {
...
}
@Entity
@DiscriminatorValue("TWO")
@Getter
@Setter
public class SecondDetails extends BaseDetails {
...
}
这很好用,但我 运行 遇到了一个问题,因为有太多单独的存储库:
@Repository
public interface OneDetailsRepository extends JpaRepository<OneDetails, String> { ... }
等等
有没有办法拥有一个可以与所有派生实体一起使用的存储库(等式 BaseDetailsRepository
)?
编辑: 我正在寻找的是这样的东西:
@Repository
public interface BaseDetailsRepository extends JpaRepository<? extends BaseDetails, String> {
OneDetails findOne(String identifier);
SecondDetails findOne(String identifier);
}
@NoRepositoryBean // Read only repository
public interface BaseDetailsRepository<T extends BaseDetails>
extends JpaRepository<T, String> {
T findOne(String identifier);
T findOne(Long id);
Iterable<T> findAll();
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
并且您还可以为每个实体拥有三个存储库:
@Transactional
public interface BaseRepository extends BaseDetailsRepository<BaseDetails> { }
@Transactional
public interface FirstDetailsRepository extends BaseDetailsRepository<BaseDetails>,JpaRepository<T extends BaseDetails, String>{ }
@Transactional
public interface SecondDetailsRepository extends BaseDetailsRepository<BaseDetails>,JpaRepository<T extends BaseDetails, String> { }
您可以进行如下操作:
存储库:BaseDetailsRepo.java
@Repository
public interface BaseDetailsRepo extends JpaRepository<BaseDetails, String>{
//make the return according to you ..it shouldn't be list....
@Query("FROM SecondDetails AS bd WHERE bd.identifier=:identifier")
public List<SecondDetails> getSecondDetailsByIdentifier(@Param("identifier") String identifier);
@Query("FROM FirstDetails AS bd WHERE bd.identifier=:identifier")
public List<FirstDetails> getFirstDetailsByIdentifier(@Param("identifier") String identifier);
}
控制器:DemoController.java
@Controller
public class DemoController {
@Autowired
private BaseDetailsRepo baseDetailsRepo;
@GetMapping(value="/test")
public ResponseEntity test(){
FirstDetails fd = new FirstDetails();
fd.setIdentifier("fd1-demo");
FirstDetails fd1 = new FirstDetails();
fd1.setIdentifier("fd2-demo");
SecondDetails sd = new SecondDetails();
sd.setIdentifier("sd1-demo");
baseDetailsRepo.save(fd);
baseDetailsRepo.save(fd1);
baseDetailsRepo.save(sd);
return new ResponseEntity("Success",HttpStatus.OK);
}
@GetMapping(value="/test/second/{id}")
public ResponseEntity getSecondDetails(@PathVariable String id){
return new ResponseEntity(baseDetailsRepo.getSecondDetailsByIdentifier(id),HttpStatus.OK);
}
@GetMapping(value="/test/first/{id}")
public ResponseEntity getFirstDetails(@PathVariable String id){
return new ResponseEntity(baseDetailsRepo.getFirstDetailsByIdentifier(id),HttpStatus.OK);
}
}