복붙노트

[SPRING] Spring 데이터 나머지를 사용할 때 모든 ID 노출

SPRING

Spring 데이터 나머지를 사용할 때 모든 ID 노출

Spring Rest 인터페이스를 사용하여 모든 ID를 노출하고 싶습니다. 나는이 기본 ID가 이런 식으로 알고있다.

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(unique=true, nullable=false)
    private Long id;

나머지 인터페이스를 통해 노출되지 않습니다.

나는 이것을 사용할 수 있다는 것을 알고있다.

    @Configuration
    public class RepositoryConfig extends RepositoryRestMvcConfiguration {
       @Override
       protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
           config.exposeIdsFor(User.class);
       }

사용자의 ID를 노출합니다.

하지만이 리포지토리 구성 메서드에서 수동으로 목록을 유지 관리하지 않으면 모든 ID를 쉽게 노출시킬 수 있습니까?

미리 감사드립니다!

해결법

  1. ==============================

    1.현재 SDR에서 제공하는 방법은 없습니다. SDR Jira 추적기의이 문제는 이것이 왜 가능하지 않은지에 대한 설명을 제공합니다.

    현재 SDR에서 제공하는 방법은 없습니다. SDR Jira 추적기의이 문제는 이것이 왜 가능하지 않은지에 대한 설명을 제공합니다.

    논증은 기본적으로 ID가 응답의 자체 링크 내에 이미 포함되어 있으므로 객체 자체의 속성으로 ID를 노출 할 필요가 없다는 것을 기본적으로 밝힙니다.

    즉, 리플렉션을 사용하여 javax.persistence.Id 주석이있는 모든 클래스를 검색 한 다음 RepositoryRestConfiguration # exposeIdsFor (Class ... domainTypes)를 호출 할 수 있습니다.

  2. ==============================

    2.Id 필드에 'Id'라는 이름을 붙이면 Id에 대한 공용 getter가 있으면 JSON에 표시된다는 것을 발견했습니다. ID는 'id'라는 JSON 키로 표시됩니다.

    Id 필드에 'Id'라는 이름을 붙이면 Id에 대한 공용 getter가 있으면 JSON에 표시된다는 것을 발견했습니다. ID는 'id'라는 JSON 키로 표시됩니다.

    예를 들면 다음과 같습니다. @Id @Column (name = "PERSON_ROLE_ID") private Long Id;

    이것은 'Id'라는 @EmbeddedId 필드뿐만 아니라 공용 getter가있는 한이 필드에서도 작동합니다. 이 경우 ID 필드는 JSON 객체로 표시됩니다.

    예를 들면 다음과 같습니다. @EmbeddedId private PrimaryKey Id;

    놀랍게도 이것은 대소 문자를 구분합니다. 'id'라는 호출 ID는 Java 필드의 더 일반적인 이름 임에도 불구하고 작동하지 않습니다.

    나는 우연히 이것을 완전히 발견했다고 말하며 이것이 받아 들여진 관례인지 또는 스프링 데이터와 REST의 이전 버전과 미래 버전에서 작동 할 것인지 모르겠습니다. 따라서 내 maven pom의 관련 부분을 버전에 민감하게 넣었습니다.

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc7</artifactId>
            <version>12.1.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
    </dependencies>
    
  3. ==============================

    3.모든 엔티티 클래스의 id 필드를 노출하려면 다음을 수행하십시오.

    모든 엔티티 클래스의 id 필드를 노출하려면 다음을 수행하십시오.

    import java.util.stream.Collectors;
    
    import javax.persistence.EntityManager;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
    import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
    
    @Configuration
    public class MyRepositoryRestConfigurerAdapter extends RepositoryRestConfigurerAdapter {
    
        @Autowired
        private EntityManager entityManager;
    
        @Override
        public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
            config.exposeIdsFor(entityManager.getMetamodel().getEntities().stream().map(e -> e.getJavaType()).collect(Collectors.toList()).toArray(new Class[0]));
        }
    
    }
    
  4. ==============================

    4.이 메서드를 사용하여 EntityManagerFactory의 모든 @Entity 클래스를 찾을 수 있습니다.

    이 메서드를 사용하여 EntityManagerFactory의 모든 @Entity 클래스를 찾을 수 있습니다.

    private List<Class<?>> getAllManagedEntityTypes(EntityManagerFactory entityManagerFactory) {
        List<Class<?>> entityClasses = new ArrayList<>();
        Metamodel metamodel = entityManagerFactory.getMetamodel();
        for (ManagedType<?> managedType : metamodel.getManagedTypes()) {
            Class<?> javaType = managedType.getJavaType();
            if (javaType.isAnnotationPresent(Entity.class)) {
                entityClasses.add(managedType.getJavaType());
            }
        }
        return entityClasses;
    }
    

    모든 엔티티 클래스의 ID를 노출하려면 다음을 수행하십시오.

    @Configuration
    public class RestConfig extends RepositoryRestMvcConfiguration {
    
        @Bean
        public RepositoryRestConfigurer repositoryRestConfigurer(EntityManagerFactory entityManagerFactory) {
            List<Class<?>> entityClasses = getAllManagedEntityTypes(entityManagerFactory);
    
            return new RepositoryRestConfigurerAdapter() {
    
                @Override
                public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
                    for (Class<?> entityClass : entityClasses) {
                        config.exposeIdsFor(entityClass);
                    }
                }
        }
    }
    
  5. ==============================

    5.이에 대한 간단한 해결책을 찾아 엔티티와 관련된 것을 피하십시오.

    이에 대한 간단한 해결책을 찾아 엔티티와 관련된 것을 피하십시오.

    @Component
    public class EntityExposingIdConfiguration extends RepositoryRestConfigurerAdapter {
    
        @Override
        public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
            try {
                Field exposeIdsFor = RepositoryRestConfiguration.class.getDeclaredField("exposeIdsFor");
                exposeIdsFor.setAccessible(true);
                ReflectionUtils.setField(exposeIdsFor, config, new ListAlwaysContains());
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
    
        class ListAlwaysContains extends ArrayList {
    
            @Override
            public boolean contains(Object o) {
                return true;
            }
        }
    }
    
  6. ==============================

    6.아마 당신은 모든 id 필드를 포함하도록 이것을 시도 할 수 있습니다. 아직 시도하지는 않았지만 계속 게시됩니다.

    아마 당신은 모든 id 필드를 포함하도록 이것을 시도 할 수 있습니다. 아직 시도하지는 않았지만 계속 게시됩니다.

     public class ExposeAllRepositoryRestConfiguration extends RepositoryRestConfiguration {
        @Override
        public boolean isIdExposedFor(Class<?> domainType) {
            return true;
            }
        }
    

    이 링크에서 발췌

  7. ==============================

    7.exposeIdsFor를 사용하여 모든 엔티티 클래스를 추가 할 수 있습니다. 엔티티를 넣은 패키지에 "db.entity"를 입력하십시오.

    exposeIdsFor를 사용하여 모든 엔티티 클래스를 추가 할 수 있습니다. 엔티티를 넣은 패키지에 "db.entity"를 입력하십시오.

    @Configuration
    public class CustomRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter {
        Logger logger = Logger.getLogger(this.getClass());
    
        @Override
        public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
            Set<String> classNameSet = ClassTool.getClassName("db.entity", false);
            for (String className : classNameSet) {
                try {
                    config.exposeIdsFor(Class.forName(className));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
    
            logger.info("exposeIdsFor : " + classNameSet);
        }
    }
    

    ClassTool은 주어진 패키지에서 클래스를 가져 오는 사용자 정의 함수입니다. 직접 작성할 수 있습니다.

  8. ==============================

    8.다음은 나를 위해 완벽하게 작동 한 것입니다 (여기 출처).

    다음은 나를 위해 완벽하게 작동 한 것입니다 (여기 출처).

    @Configuration
    public class RepositoryRestConfig extends RepositoryRestConfigurerAdapter {
    
      @Override
      public void configureRepositoryRestConfiguration(final RepositoryRestConfiguration config) {
    
        final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
            false);
        provider.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
    
        final Set<BeanDefinition> beans = provider.findCandidateComponents("com.your.domain");
    
        for (final BeanDefinition bean : beans) {
          try {
            config.exposeIdsFor(Class.forName(bean.getBeanClassName()));
          } catch (final ClassNotFoundException e) {
            // Can't throw ClassNotFoundException due to the method signature. Need to cast it
            throw new IllegalStateException("Failed to expose `id` field due to", e);
          }
        }
      }
    }
    

    @Entity 주석으로 모든 bean을 찾아 노출합니다.

  9. ==============================

    9.이 구성을 시도하십시오. 그것은 나를 위해 완벽하게 작동합니다.

    이 구성을 시도하십시오. 그것은 나를 위해 완벽하게 작동합니다.

    @Configuration
    public class RestConfiguration extends RepositoryRestConfigurerAdapter{
    
          @PersistenceContext
          private EntityManager entityManager;
    
          @Override
          public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
               //TODO: Expose for specific entity!
               //config.exposeIdsFor(Officer.class);
               //config.exposeIdsFor(Position.class);
    
               //TODO: Expose id for all entities!
               entityManager.getMetamodel().getEntities().forEach(entity->{
                    try {
                         System.out.println("Model: " + entity.getName());
                         Class<? extends Object> clazz = Class.forName(String.format("yourpackage.%s", entity.getName()));
                         config.exposeIdsFor(clazz);
                    } catch (Exception e) {
                         System.out.println(e.getMessage());
                    }
                });
        }
    }
    
  10. from https://stackoverflow.com/questions/30912826/expose-all-ids-when-using-spring-data-rest by cc-by-sa and MIT license