Spring Data 저장소의 사용자 정의 방법 구현 및 REST를 통해 노출
Spring Data 저장소에 사용자 지정 메서드를 추가하려고 합니다.PersonRepository
1.3 Spring 데이터 저장소에 대한 사용자 정의 구현에서 설명한 바와 같이 REST를 통해 이러한 방법을 노출시킵니다.초기 코드는 REST 샘플을 사용한 JPA 데이터 액세스에서 가져온 것이며, 추가/수정된 클래스에 대한 코드는 다음과 같습니다.
interface PersonRepositoryCustom {
List<Person> findByFistName(String name);
}
class PersonRepositoryImpl implements PersonRepositoryCustom, InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// initialization here
}
@Override
public List<Person> findByFistName(String name) {
// find the list of persons with the given firstname
}
}
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(@Param("name") String name);
}
응용프로그램을 실행하고 방문할 때http://localhost:8080/portfolio/search/
다음과 같은 응답 본문을 얻습니다.
{
"_links" : {
"findByLastName" : {
"href" : "http://localhost:8080/people/search/findByLastName{?name}",
"templated" : true
}
}
}
왜죠findByFirstName
에서 사용 가능한 경우에도 노출되지 않습니다.PersonRepository
인터페이스?
또한 REST를 통해 노출될 저장소를 동적/프로그램적으로 추가하는 방법이 있습니까?
이틀 후에 저는 이렇게 해결했습니다.
사용자 지정 리포지토리 인터페이스:
public interface PersonRepositoryCustom {
Page<Person> customFind(String param1, String param2, Pageable pageable);
}
사용자 지정 리포지토리 구현
public class PersonRepositoryImpl implements PersonRepositoryCustom{
@Override
public Page<Person> customFind(String param1, String param2, Pageable pageable) {
// custom query by mongo template, entity manager...
}
}
Spring 데이터 저장소:
@RepositoryRestResource(collectionResourceRel = "person", path = "person")
public interface PersonRepository extends MongoRepository<Person, String>, PersonRepositoryCustom {
Page<Person> findByName(@Param("name") String name, Pageable pageable);
}
Bean 리소스 표현
public class PersonResource extends org.springframework.hateoas.Resource<Person>{
public PersonResource(Person content, Iterable<Link> links) {
super(content, links);
}
}
리소스 어셈블러
@Component
public class PersonResourceAssembler extends ResourceAssemblerSupport<Person, PersonResource> {
@Autowired
RepositoryEntityLinks repositoryEntityLinks;
public PersonResourceAssembler() {
super(PersonCustomSearchController.class, PersonResource.class);
}
@Override
public PersonResource toResource(Person person) {
Link personLink = repositoryEntityLinks.linkToSingleResource(Person.class, person.getId());
Link selfLink = new Link(personLink.getHref(), Link.REL_SELF);
return new PersonResource(person, Arrays.asList(selfLink, personLink));
}
}
사용자 지정 스프링 MVC 컨트롤러
@BasePathAwareController
@RequestMapping("person/search")
public class PersonCustomSearchController implements ResourceProcessor<RepositorySearchesResource> {
@Autowired
PersonRepository personRepository;
@Autowired
PersonResourceAssembler personResourceAssembler;
@Autowired
private PagedResourcesAssembler<Person> pagedResourcesAssembler;
@RequestMapping(value="customFind", method=RequestMethod.GET)
public ResponseEntity<PagedResources> customFind(@RequestParam String param1, @RequestParam String param2, @PageableDefault Pageable pageable) {
Page personPage = personRepository.customFind(param1, param2, pageable);
PagedResources adminPagedResources = pagedResourcesAssembler.toResource(personPage, personResourceAssembler);
if (personPage.getContent()==null || personPage.getContent().isEmpty()){
EmbeddedWrappers wrappers = new EmbeddedWrappers(false);
EmbeddedWrapper wrapper = wrappers.emptyCollectionOf(Person.class);
List<EmbeddedWrapper> embedded = Collections.singletonList(wrapper);
adminPagedResources = new PagedResources(embedded, adminPagedResources.getMetadata(), adminPagedResources.getLinks());
}
return new ResponseEntity<PagedResources>(adminPagedResources, HttpStatus.OK);
}
@Override
public RepositorySearchesResource process(RepositorySearchesResource repositorySearchesResource) {
final String search = repositorySearchesResource.getId().getHref();
final Link customLink = new Link(search + "/customFind{?param1,param2,page,size,sort}").withRel("customFind");
repositorySearchesResource.add(customLink);
return repositorySearchesResource;
}
}
이러한 메소드가 노출되지 않는 이유는 기본적으로 사용자 지정 저장소 메소드에서 원하는 모든 것을 구현할 수 있기 때문에 특정 리소스를 지원하는 올바른 HTTP 메소드에 대해 추론할 수 없습니다.
당신의 경우에는 플레인을 사용해도 괜찮을 것입니다.GET
다른 경우에는 다음과 같이 해야 할 수도 있습니다.POST
그 방법의 실행은 부작용이 있기 때문입니다.
이에 대한 현재 솔루션은 저장소 메서드를 호출하는 사용자 지정 컨트롤러를 만드는 것입니다.
위해서GET
내가 사용한 방법은 다음과 같습니다.
- 더미를 작성합니다.
@Query
저장소의 메서드(LogRepository.java) - 동일한 메서드가 선언된 사용자 지정 인터페이스 생성(LogRepositoryCustom.java)
- 사용자 지정 인터페이스의 구현 생성(LogRepositoryImppl.java)
이 접근 방식을 사용하면 투영 및 리소스 조립을 관리할 필요가 없습니다.
@RepositoryRestResource(collectionResourceRel = "log", path = "log")
public interface LogRepository extends PagingAndSortingRepository<Log, Long>,
LogRepositoryCustom {
//NOTE: This query is just a dummy query
@Query("select l from Log l where l.id=-1")
Page<Log> findAllFilter(@Param("options") String options,
@Param("eid") Long[] entityIds,
@Param("class") String cls,
Pageable pageable);
}
public interface LogRepositoryCustom {
Page<Log> findAllFilter(@Param("options") String options,
@Param("eid") Long[] entityIds,
@Param("class") String cls,
Pageable pageable);
}
구현에서는 저장소 메서드를 사용하거나 지속성 계층으로 직접 이동할 수 있습니다.
public class LogRepositoryImpl implements LogRepositoryCustom{
@Autowired
EntityManager entityManager;
@Autowired
LogRepository logRepository;
@Override
public Page<Log> findAllFilter(
@Param("options") String options,
@Param( "eid") Long[] entityIds,
@Param( "class" ) String cls,
Pageable pageable) {
//Transform kendoui json options to java object
DataSourceRequest dataSourceRequest=null;
try {
dataSourceRequest = new ObjectMapper().readValue(options, DataSourceRequest.class);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
Session s = entityManager.unwrap(Session.class);
Junction junction = null;
if (entityIds != null || cls != null) {
junction = Restrictions.conjunction();
if (entityIds != null && entityIds.length > 0) {
junction.add(Restrictions.in("entityId", entityIds));
}
if (cls != null) {
junction.add(Restrictions.eq("cls", cls));
}
}
return dataSourceRequest.toDataSourceResult(s, Log.class, junction);
}
답은 당신이 지시를 따르지 않았다는 것입니다.당신의.PersonRepository
둘 다 확장해야 합니다.PagingAndSortingRepository<Person, Long>
그리고.PersonRepositoryCustom
당신이 추구하는 것을 이루기 위해.자세한 내용은 https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/ #stitutories.custom-configuration을 참조하십시오.
또한 특정 스토리지 유형에 맞는 맞춤형 저장소 팩토리를 구현하는 방법도 사용했습니다.
수할있다에서 확장할 수 .RepositoryFactoryBeanSupport
당신만의 것을 만듭니다.PersistentEntityInformation
사용자 지정 데이터 스토리지 유형에 대한 기본 리포폴에서 CRUD ops를 처리합니다. 참조JpaRepositoryFactoryBean
총 10개의 클래스를 구현해야 하지만 재사용이 가능합니다.
사용해 보십시오.
class PersonRepositoryCustomImpl implements PersonRepositoryCustom, InitializingBean {
...
}
구현 클래스 이름은 다음과 같아야 합니다.PersonRepositoryCustomImpl
에 PersonRepositoryImpl
.
언급URL : https://stackoverflow.com/questions/25201306/implementing-custom-methods-of-spring-data-repository-and-exposing-them-through
'programing' 카테고리의 다른 글
Android 4.0용 AVD를 만드는 방법 (0) | 2023.08.11 |
---|---|
PowerShell:Out-File은 왜 긴 줄을 더 작은 줄로 나누나요? (0) | 2023.08.11 |
SQL Server 로그인을 코드에 저장(C#) (0) | 2023.08.11 |
APP_INITIALIZER는 "순환 종속성을 인스턴스화할 수 없습니다!리디렉션하는 사용자 지정 Http 공급자와 함께 사용할 경우 ApplicationRef_" (0) | 2023.08.06 |
MySQL - INSERT 문 안에서 문자열 값을 DATTIME 형식으로 구문 분석하는 방법은 무엇입니까? (0) | 2023.08.06 |