Unable to retrieve Spring HATEOAS embedded resourc

2020-03-26 13:50发布

I am unable to retrieve embedded .I am using Spring boot ,spring data rest and spring JPA. I have 3 tables in data base

  • user
  • competency
  • user_competency (join/composite table with extra column)

User

@Entity
@Table(name = "\"user\"", schema = "public")
@JsonIdentityInfo(
          generator = ObjectIdGenerators.IntSequenceGenerator.class, 
          property = "userId")
public class User implements java.io.Serializable {

    private Long userId;

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)

    @Column(name = "user_id", unique = true, nullable = false)
    public Long getUserId() {
        return this.userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    private Set<UserCompetency> userCompetencies = new HashSet<UserCompetency>(0);

        @OneToMany(fetch = FetchType.EAGER,cascade = {CascadeType.ALL}, mappedBy = "user")
    public Set<UserCompetency> getUserCompetencies() {
        return this.userCompetencies;
    }

    public void setUserCompetencies(Set<UserCompetency> userCompetencies) {
        this.userCompetencies = userCompetencies;
    }

}

**Competency**



 @Entity
    @Table(name = "competency", schema = "public")
    @JsonIdentityInfo(
              generator = ObjectIdGenerators.IntSequenceGenerator.class, 
              property = "competencyId")
    public class Competency implements java.io.Serializable {


        private Long competencyId;
        private Set<UserCompetency> userCompetencies = new HashSet<UserCompetency>(0);

        @Id @GeneratedValue(strategy = GenerationType.IDENTITY)

        @Column(name = "competency_id", unique = true, nullable = false)
        public Long getCompetencyId() {
            return this.competencyId;
        }

        public void setCompetencyId(Long competencyId) {
            this.competencyId = competencyId;
        }

            @OneToMany(fetch = FetchType.LAZY, mappedBy = "competency")
        public Set<UserCompetency> getUserCompetencies() {
            return this.userCompetencies;
        }

        public void setUserCompetencies(Set<UserCompetency> userCompetencies) {
            this.userCompetencies = userCompetencies;
        }
    }   

UserCompetency

    @Entity
    @Table(name = "user_competency", schema = "public")
    @JsonIdentityInfo(
              generator =ObjectIdGenerators.IntSequenceGenerator.class, 
              property = "id")
    public class UserCompetency implements java.io.Serializable {
        private UserCompetencyId id;
        private Level level;
        private User user;
        private Competency competency;

        @EmbeddedId

        @AttributeOverrides({
                @AttributeOverride(name = "competencyId", column = @Column(name = "competency_id", nullable = false)),
                @AttributeOverride(name = "userId", column = @Column(name = "user_id", nullable = false)) })
        public UserCompetencyId getId() {
            return this.id;
        }

        public void setId(UserCompetencyId id) {
            this.id = id;
        }

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "level_id")
        public Level getLevel() {
            return this.level;
        }

        public void setLevel(Level level) {
            this.level = level;
        }

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false)
        public User getUser() {
 return this.user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @ManyToOne(fetch = FetchType.EAGER,cascade=CascadeType.ALL)
    @JoinColumn(name = "competency_id", nullable = false, insertable = false, updatable = false)
    public Competency getCompetency() {
        return this.competency;
    }

    public void setCompetency(Competency competency) {
        this.competency = competency;
    }
}

UserCompetencyId

@Embeddable
public class UserCompetencyId implements java.io.Serializable {

    private Long competencyId;
    private Long userId;

    public UserCompetencyId() {
    }

    public UserCompetencyId(Long competencyId, Long userId) {
        this.competencyId = competencyId;
        this.userId = userId;
    }


    @Column(name = "competency_id", nullable = false)
    public Long getCompetencyId() {
        return this.competencyId;
    }

    public void setCompetencyId(Long competencyId) {
        this.competencyId = competencyId;
    }

    @Column(name = "user_id", nullable = false)
    public Long getUserId() {
        return this.userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public boolean equals(Object other) {
        if ((this == other))
            return true;
        if ((other == null))
            return false;
        if (!(other instanceof UserCompetencyId))
            return false;
        UserCompetencyId castOther = (UserCompetencyId) other;

        return (this.getCompetencyId() == castOther.getCompetencyId()) && (this.getUserId() == castOther.getUserId());
    }    
}

UserCompetencyRepository

  public interface UserCompetencyRepository extends JpaRepository<UserCompetency, UserCompetencyId> {

}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>Demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>Demo</name>
    <description>Demo api </description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-rest-hal-browser</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-rest-webmvc</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

and I want to perform GET using URI,it return me embedded object and cannot get real value of objects attributes
GET http://localhost:8080/userCompetencies

enter image description here


How Can I get attribute values of User and Competency object where userId=8 Help is required

After implementing suggested Projection Issue still not resolved and here is screen shot
enter image description here

2条回答
唯我独甜
2楼-- · 2020-03-26 14:24

One way would be to use projections like for example:

@Projection(name = "edit" , types = Employee.class)
public interface EditEmployeeProjection {
    String getFirstName();
    String getLastName();
    Set<Project> getProjects();
}

With this the project list will be embedded in the result for http://localhost:8080/api/employee/1?projection=edit

Projections would be used automatically if you add excerptProjection to you repository like described here: How to expose a complete tree structure with Spring Data REST and HATEOAS?

See for example here: https://shinesolutions.com/2015/04/15/spring-data-rest-and-projections/

EDITED

In you case a projection would look like:

@Projection(name = "edit" , types = UserCompetency.class)
public interface UserCompetencyProjection {
    User getUser();
    Competency getCompetency();
}

With http://localhost:8080/userCompetencies?projection=edit you would then see wanted result.

enter image description here

EDITED 2 The code I used:

Competency.class

@Entity
@Table(name = "competency", schema = "public")
@JsonIdentityInfo(
          generator = ObjectIdGenerators.IntSequenceGenerator.class,
          property = "competencyId")
public class Competency implements java.io.Serializable {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "competency_id", unique = true, nullable = false)
    private Long competencyId;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "competency")
    private List<UserCompetency> userCompetencies = new ArrayList<>();

UserCompetency.class

@Entity
@Table(name = "user_competency", schema = "public")
@JsonIdentityInfo(
          generator = ObjectIdGenerators.IntSequenceGenerator.class,
          property = "id")
public class UserCompetency implements java.io.Serializable {

    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name = "competencyId", column = @Column(name = "competency_id", nullable = false)),
        @AttributeOverride(name = "userId", column = @Column(name = "user_id", nullable = false)) })
    private UserCompetencyId id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false)
    private User user;

    @ManyToOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
    @JoinColumn(name = "competency_id", nullable = false, insertable = false, updatable = false)
    private Competency competency;

UserCompetencyId.class

@Embeddable
public class UserCompetencyId implements java.io.Serializable {

    @Column(name = "competency_id", nullable = false)
    private Long competencyId;

    @Column(name = "user_id", nullable = false)
    private Long userId;

UserCompetencyRepository.class

@RepositoryRestResource(excerptProjection = UserCompetencyProjection.class)    
public interface UserCompetencyRepository extends JpaRepository<UserCompetency, UserCompetencyId> {

After Implementing This ,In my case its not working to show desired jason   [![enter image description here][2]][2]
查看更多
淡お忘
3楼-- · 2020-03-26 14:26

It worked out ,actually i was missing annotation of
@RepositoryRestResource(excerptProjection = UserCompetencyProjection.class) on UserCompetencyRepository class now the output look like this I am skipping as it is output , and putting necessary output. enter image description here

enter image description here enter image description here

查看更多
登录 后发表回答