web-dev-qa-db-ja.com

Spring Data Restを使用するときにすべてのIDを公開する

Spring Restインターフェースを使用してすべてのIDを公開したいのですが。

デフォルトでは、このようなIDは残りのインターフェースを介して公開されないことを知っています。

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

これを使用してUserのIDを公開できることを知っています。

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

しかし、このconfigureRepositoryRestConfigurationメソッドのリストを手動で維持せずにすべてのIDを公開する簡単な方法はありますか?

22
Baiteman

現在、SDRが提供する方法はありません。 この問題 SDR Jiraトラッカーで、これがなぜ不可能であるか(おそらく可能ではないか)についていくつかの説明が提供されています。

基本的には、IDは応答のselfリンク内に既に含まれているため、オブジェクト自体のプロパティとして公開する必要はありません。

つまり、リフレクションを使用して、_javax.persistence.Id_アノテーションを持つすべてのクラスを取得し、RepositoryRestConfiguration#exposeIdsFor(Class<?>... domainTypes)を呼び出すことができる場合があります。

11
Justin Lewis

すべてのエンティティクラスの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]));
    }

}
15
mekazu

_@Id_フィールドに 'Id'という名前を付けると、IdのパブリックゲッターがあればJSONに表示されることがわかりました。 IDは「id」というJSONキーとして表示されます

例:@Id @Column(name="PERSON_ROLE_ID") private Long Id;

これは、 'Id'と呼ばれる_@EmbeddedId_フィールドでも、パブリックゲッターがある限り機能します。この場合、IDのフィールドはJSONオブジェクトとして表示されます。

例:_@EmbeddedId private PrimaryKey Id;_

驚いたことに、これは大文字と小文字を区別します。Javaフィールドの従来の名前であるとしても、id 'id'の呼び出しは機能しません。

私はこれを完全に偶然発見したので、これが受け入れられた規則であるのか、Spring Dataおよび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>
_
15
Mark

このメソッドを使用して、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);
                }
            }
    }
}
2
Dario Seidl

この構成を試してください。それは私にとっては完璧に機能します。

@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());
                }
            });
    }
}
1
Phearun Rath

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は、指定されたパッケージからクラスを取得するためのカスタム関数です。自分で書くことができます。

0
kidfruit

これは私にとって完璧に機能したものです( source here ):

@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を見つけて公開します。

0
Stephan

おそらく、これを試してすべてのidフィールドを含めることができます。私はまだ試していませんが、投稿し続けます。

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

このリンクからの抜粋

0
raksja

次のコードはよりきれいに見えます:

.exposeIdsFor(entityManager.getMetamodel().getEntities().stream().map(entityType -> entityType.getJavaType()).toArray(Class[]::new))
0

あなたはこの解決策を試すことができます:-最初のインポート reflections ライブラリをPOMファイルに:

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.11</version>
</dependency>

-次に、RepositoryConfigクラスを次のように変更します。

@Configuration
public class RepositoryConfig extends RepositoryRestMvcConfiguration {
    @Override
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        Reflections reflections = new Reflections("com.example.entity");
        Set<Class<?>> idExposedClasses = reflections.getTypesAnnotatedWith(Entity.class, false);
        idExposedClasses.forEach(config::exposeIdsFor);
        return config;
    }
}

"com.example.entity"をあなたのエンティティに変更しますpackageといいです。幸運を!

0
Terry

関連するエンティティを見つけるのを避けて、このための簡単な解決策を見つけてください。

@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;
        }
    }
}
0
David B.