kn4*_*4ls 6 java spring elasticsearch jhipster spring-data-elasticsearch
我开始在Spring Boot 1.3.1上使用Spring Data Elasticsearch,我想使用在我的数据库中使用的相同实体,它有复合键.
实体类:
@IdClass(PassengerPk.class)
@Table(name = "passenger")
@Document(indexName="passenger")
public class Passenger implements Serializable {
@Id
@ManyToOne
@JoinColumn(columnDefinition="long", name="user_id", referencedColumnName="id")
private User user;
@Id
@ManyToOne
@JoinColumn(columnDefinition="long", name="scheduler_id", referencedColumnName="id")
private Scheduler scheduler;
@Column(name = "is_active")
private Boolean isActive;
...
}
Run Code Online (Sandbox Code Playgroud)
关键课程:
public class PassengerPk implements Serializable {
private Long user;
private Long scheduler;
public PassengerPk() {
}
public PassengerPk(Long user, Long scheduler) {
this.user = user;
this.scheduler = scheduler;
}
...
}
Run Code Online (Sandbox Code Playgroud)
JPA Elasticsearch存储库:
public interface PassengerSearchRepository extends ElasticsearchRepository<Passenger, PassengerPk> {
}
Run Code Online (Sandbox Code Playgroud)
数据库: 数据库关系
如果我尝试编译此代码,我会收到此错误.
Caused by: java.lang.IllegalArgumentException: Unsuppored ID type class com.dualion.test.domain.PassengerPk
at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory.getRepositoryBaseClass(ElasticsearchRepositoryFactory.java:79) ~[spring-data-elasticsearch-1.3.1.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepositoryInformation(RepositoryFactorySupport.java:238) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:181) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactoryBean.afterPropertiesSet(ElasticsearchRepositoryFactoryBean.java:55) ~[spring-data-elasticsearch-1.3.1.RELEASE.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
... 71 common frames omitted
Run Code Online (Sandbox Code Playgroud)
我如何修改我的代码?
谢谢
我在其他地方读过相关答案并得出结论这是不可能的;然而,我的固执最终战胜了我,我找到了解决办法。
太长了;强制 spring 使用一个新的存储库,该存储库采用复合 id 的 hashCode 并使用其字符串值作为其 id。
脚步...
创建一个Repository
可以处理复合 id 的新对象:
public class HashKeyedRepository<T, ID extends Serializable> extends AbstractElasticsearchRepository<T, ID> {
public HashKeyedRepository() {
super();
}
public HashKeyedRepository(ElasticsearchEntityInformation<T, ID> metadata,
ElasticsearchOperations elasticsearchOperations) {
super(metadata, elasticsearchOperations);
}
public HashKeyedRepository(ElasticsearchOperations elasticsearchOperations) {
super(elasticsearchOperations);
}
@Override
protected String stringIdRepresentation(ID id) {
return String.valueOf(id.hashCode());
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这假设您已正确实现.hashCode
复合 id 类以正常工作。
接下来,您必须创建一个RepositoryFactoryBean
将返回此新值的新值Repository
:
public class CustomElasticsearchRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends ElasticsearchRepositoryFactoryBean<T, S, ID> {
private ElasticsearchOperations operations;
public CustomElasticsearchRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
public void setElasticsearchOperations(ElasticsearchOperations operations) {
super.setElasticsearchOperations(operations);
Assert.notNull(operations);
this.operations = operations;
}
@Override
protected RepositoryFactorySupport createRepositoryFactory() {
return new ElasticsearchRepositoryFactory(operations) {
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
if (!Integer.class.isAssignableFrom(metadata.getIdType()) && !Long.class.isAssignableFrom(metadata.getIdType()) && !Double.class.isAssignableFrom(metadata.getIdType()) && metadata.getIdType() != String.class && metadata.getIdType() != UUID.class) {
return HashKeyedRepository.class;
}
return super.getRepositoryBaseClass(metadata);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
最后,在启用存储库时,指定您的新RepositoryFactoryBean
类:
@EnableElasticsearchRepositories(basePackages = "xxx.xxx.repository.search", repositoryFactoryBeanClass = CustomElasticsearchRepositoryFactoryBean.class)
Run Code Online (Sandbox Code Playgroud)
如果使用截至本文撰写时支持的任何 ID(即字符串、UUID、数字),则此实现将回退到默认值。我不知道它是否是一个很好的解决方案,因为可能与 .hashCode 发生冲突,但它现在对我有用。
PS我正在使用lombok
s@Data
为我自动生成 .hashCode 。
PPS我见过其他人(非java)提到的另一个解决方案是对id 的序列化版本(即JSON)进行base64 编码。我认为这可以保证不会发生冲突,但您必须确保删除任何多余的字符(即空格)并保证属性的顺序才能使其有效。
归档时间: |
|
查看次数: |
2072 次 |
最近记录: |