Java 使用 Spring Data Rest 时暴露所有 ID
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30912826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Expose all IDs when using Spring Data Rest
提问by Baiteman
I'd like to expose all IDs using a Spring Rest interface.
我想使用 Spring Rest 接口公开所有 ID。
I know that per default an ID like this will not be exposed via the rest interface:
我知道默认情况下,这样的 ID 不会通过其余接口公开:
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(unique=true, nullable=false)
private Long id;
I'm aware that I can use this to expose the ID for User
:
我知道我可以使用它来公开以下 ID User
:
@Configuration
public class RepositoryConfig extends RepositoryRestMvcConfiguration {
@Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(User.class);
}
}
But is there an easy way to expose all IDs without manually maintaining a list in this configureRepositoryRestConfiguration
method?
但是有没有一种简单的方法来公开所有 ID,而无需在此configureRepositoryRestConfiguration
方法中手动维护列表?
采纳答案by Justin Lewis
Currently, there is no way to do this provided by SDR. This issueon the SDR Jira tracker gives some explanation as to why this isn't (and perhaps shouldn't) be possible.
目前,SDR 没有提供这种方法。SDR Jira 跟踪器上的这个问题解释了为什么这不可能(也许不应该)。
The argument is basically that since the IDs are already contained within the self
links in the response, you don't need to expose them as properties of the object itself.
论点基本上是因为 ID 已经包含在self
响应中的链接中,所以您不需要将它们作为对象本身的属性公开。
That said, you may be able to use reflection to retrieve all classes that have a javax.persistence.Id
annotation and then call RepositoryRestConfiguration#exposeIdsFor(Class<?>... domainTypes)
.
也就是说,您可以使用反射来检索所有具有javax.persistence.Id
注释的类,然后调用RepositoryRestConfiguration#exposeIdsFor(Class<?>... domainTypes)
.
回答by Mark
I discovered that if you name the @Id
field 'Id
' it will display in the JSON if you have a public getter for the Id
. The Id will show up as a JSON key called 'id
'
我发现,如果您将@Id
字段命名为' Id
',如果您有一个公共的 .getter,它将显示在 JSON 中Id
。Id 将显示为名为 ' id
'的 JSON 密钥
For example: @Id @Column(name="PERSON_ROLE_ID") private Long Id;
例如: @Id @Column(name="PERSON_ROLE_ID") private Long Id;
This also works for @EmbeddedId
fields called 'Id
' as well as long as it has a public getter. In this case the fields of the Id will show up as a JSON object.
这也适用于@EmbeddedId
名为“ Id
”的字段,只要它具有公共 getter。在这种情况下,Id 的字段将显示为 JSON 对象。
For example: @EmbeddedId private PrimaryKey Id;
例如: @EmbeddedId private PrimaryKey Id;
Surprisingly this is case sensitive, calling id 'id
' doesn't work even though it would be a more conventional name for a Java field.
令人惊讶的是,这是区分大小写的,调用 id ' id
' 不起作用,即使它是 Java 字段的更传统的名称。
I should say that I discovered this completely by accident so I don't know if this is an accepted convention or will work with previous or future versions of Spring Data and REST. Therefore I have included the relevant parts of my maven pom just incase it's sensittive to versions...
我应该说我完全是偶然发现的,所以我不知道这是否是公认的约定,或者是否适用于 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>
回答by raksja
Proabably you can try this to include all id fields. I havent tried it yet, but will keep posted.
很可能你可以试试这个来包含所有的 id 字段。我还没有尝试过,但会继续发布。
public class ExposeAllRepositoryRestConfiguration extends RepositoryRestConfiguration {
@Override
public boolean isIdExposedFor(Class<?> domainType) {
return true;
}
}
回答by Dario Seidl
You can use this method to find all @Entity
classes of the EntityManagerFactory:
您可以使用此方法查找@Entity
EntityManagerFactory 的所有类:
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;
}
then, to expose the IDs for all your entity classes:
然后,公开所有实体类的 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);
}
}
}
}
回答by kidfruit
You can add all your entity classes by exposeIdsFor. Replace "db.entity" to whick package you put your entities.
您可以通过ExposureIdsFor添加所有实体类。将“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);
}
}
The ClassTool is my custom function to get class from given package, you can write by yourself.
ClassTool 是我的自定义函数,用于从给定的包中获取类,您可以自己编写。
回答by Stephan
Here is what worked perfectly for me (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);
}
}
}
}
It finds all beans with the @Entity annotation and exposes them.
它找到所有带有 @Entity 注释的 bean 并公开它们。
回答by mekazu
If you want to expose the id field for all your entity classes:
如果要公开所有实体类的 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]));
}
}
回答by Phearun Rath
Try this configuration. It works perfectly fine for me.
试试这个配置。它对我来说非常好。
@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());
}
});
}
}
回答by David B.
Please find a simple solution for this, avoiding to find entities related.
请为此找到一个简单的解决方案,避免查找相关实体。
@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;
}
}
}
回答by Francois Gengler
Following piece of code looks prettier:
以下代码看起来更漂亮:
.exposeIdsFor(entityManager.getMetamodel().getEntities().stream().map(entityType -> entityType.getJavaType()).toArray(Class[]::new))