弹簧数据rest与复合主键

我使用spring数据rest来讨论crud。 但是当实体具有复合主键时,我不知道如何通过提供主键来获取实体。

河流类:

@Entity public class River { private RiverPK id; private Double length; private Timestamp date; private String comment; @Basic @Column(name = "length") public Double getLength() { return length; } public void setLength(Double length) { this.length = length; } @Basic @Column(name = "date") public Timestamp getDate() { return date; } public void setDate(Timestamp date) { this.date = date; } @Basic @Column(name = "comment") public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } @Id public RiverPK getId() { return id; } public void setId(RiverPK id) { this.id = id; } } 

RiverPK类:

 @Embeddable public class RiverPK implements Serializable { private String name; private int upcode; private int downcode; @Column(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name = "upcode") public int getUpcode() { return upcode; } public void setUpcode(int upcode) { this.upcode = upcode; } @Column(name = "downcode") public int getDowncode() { return downcode; } public void setDowncode(int downcode) { this.downcode = downcode; } } 

RiverDAO课程:

 @RepositoryRestResource(path = "river") public interface RiverDAO extends JpaRepository { } 

然后我可以通过调用get http:// localhost:8080 / river /来获取河流数据,并通过调用post http:// localhost:8080 / river / {river json}创建新的实体到db

河杰森是:

 id": { "name": "1", "upcode": 2, "downcode": 3 }, "length": 4.4, "date": 1493740800000, "comment": "6" } 

在spring data rest doc中,它应该能够调用get localhost:8080 / river / 1(主键)来获取主键为1的实体。当实体只有一个主键时,这可以工作。 但我的实体河有复合主键作为RiverPK。 如果我调用get localhost:8080 / river / {name =’1’,upcode = 2,downcode = 3},则返回错误“无转换器发现能够从类型[java.lang.String]转换为类型[com .example.db.entity.RiverPK]“,我的意思是使用spring {name =’1’,upcode = 2,downcode = 3}作为String,但不是RiverPK类型。

问题是如何使用复合主键调用get \ put \ delete作为其他正常实体?

你可以看一下jira问题: https : //jira.spring.io/browse/DATAREST-598

这条评论对您来说可能特别有趣

https://jira.spring.io/browse/DATAREST-598?focusedCommentId=117740&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-117740

在那里你还找到了一个示例项目的github链接 。 它使用BackendIdConverter将复合键转换为字符串并返回。 因此,技巧是将您的复合ID转换为可用作路径段的字符串。

这个答案对你来说也很有趣https://stackoverflow.com/a/31830586/5371736

在从具有复合ID的实体的Customizing HATEOAS链接生成中学习之后,我发现了一个更通用的解决方案。

首先,创建一个SpringUtil来从spring获取bean。

 import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if(SpringUtil.applicationContext == null) { SpringUtil.applicationContext = applicationContext; } } public static ApplicationContext getApplicationContext() { return applicationContext; } public static Object getBean(String name){ return getApplicationContext().getBean(name); } public static  T getBean(Class clazz){ return getApplicationContext().getBean(clazz); } public static  T getBean(String name,Class clazz){ return getApplicationContext().getBean(name, clazz); } } 

然后,实现BackendIdConverter。

 import com.alibaba.fastjson.JSON; import com.example.SpringUtil; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.webmvc.spi.BackendIdConverter; import org.springframework.stereotype.Component; import javax.persistence.EmbeddedId; import javax.persistence.Id; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.net.URLDecoder; import java.net.URLEncoder; @Component public class CustomBackendIdConverter implements BackendIdConverter { @Override public boolean supports(Class delimiter) { return true; } @Override public Serializable fromRequestId(String id, Class entityType) { if (id == null) { return null; } //first decode url string if (!id.contains(" ") && id.toUpperCase().contains("%7B")) { try { id = URLDecoder.decode(id, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } //deserialize json string to ID object Object idObject = null; for (Method method : entityType.getDeclaredMethods()) { if (method.isAnnotationPresent(Id.class) || method.isAnnotationPresent(EmbeddedId.class)) { idObject = JSON.parseObject(id, method.getGenericReturnType()); break; } } //get dao class from spring Object daoClass = null; try { daoClass = SpringUtil.getBean(Class.forName("com.example.db.dao." + entityType.getSimpleName() + "DAO")); } catch (ClassNotFoundException e) { e.printStackTrace(); } //get the entity with given primary key JpaRepository simpleJpaRepository = (JpaRepository) daoClass; Object entity = simpleJpaRepository.findOne((Serializable) idObject); return (Serializable) entity; } @Override public String toRequestId(Serializable id, Class entityType) { if (id == null) { return null; } String jsonString = JSON.toJSONString(id); String encodedString = ""; try { encodedString = URLEncoder.encode(jsonString, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return encodedString; } } 

之后。 你可以做你想做的。

下面有一个示例。

  • 如果实体具有单个属性pk,则可以正常使用localhost:8080 / demo / 1。 根据我的代码,假设pk有注释“@Id”。
  • 如果实体已经组成了pk,假设pk是demoId类型,并且注释为“@EmbeddedId”,则可以使用localhost:8080 / demo / {demoId json}来获取/放置/删除。 你的自我链接也是一样的。