복붙노트

[SPRING] 복합 기본 키로 봄 데이터 휴식

SPRING

복합 기본 키로 봄 데이터 휴식

나는 봄 데이터 휴식을 사용한다. 그러나 엔티티가 복합 기본 키를 가지고있을 때 기본 키를 제공하여 엔티티를 얻는 방법을 모른다.

강 클래스 :

@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<River, RiverPK> {
}

그런 다음 http : // localhost : 8080 / river /을 호출하여 강 데이터를 가져올 수 있으며 http : // localhost : 8080 / river / {river json} 콜 포스트를 통해 db에 새로운 엔티티를 만들 수 있습니다.

강 json은 다음과 같습니다.

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] ", 즉 스프링 사용 {name = '1', upcode = 2, downcode = 3}을 문자열로 나타내지 만 RiverPK 유형은 아닙니다.

질문은 복합 기본 키를 다른 일반 엔티티로 사용하여 get \ put \ delete를 호출하는 방법입니다.

해결법

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

    1.살펴볼 수있는 jira 문제가 있습니다. https://jira.spring.io/browse/DATAREST-598

    살펴볼 수있는 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

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

    2.composite id를 가진 엔티티에 대한 HATEOAS 링크 생성을 커스터마이징 한 결과, 훨씬 일반적인 솔루션을 발견했습니다.

    composite id를 가진 엔티티에 대한 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> T getBean(Class<T> clazz){
            return getApplicationContext().getBean(clazz);
        }
    
        public static <T> T getBean(String name,Class<T> 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;
        }
    }
    

    그 후. 당신이 원하는 것을 할 수 있습니다.

    아래 샘플이 있습니다.

  3. from https://stackoverflow.com/questions/43763250/spring-data-rest-with-composite-primary-key by cc-by-sa and MIT license