Search code examples
reactjshibernatespring-bootspring-data-resthateoas

Spingboot React Hypermedia string id


I am building a web app using SpringBoot, Hibernate, and React. I have had no troubles using the spring tutorials to create 'normal' objects with autogenerated Id's. For my user table I don't quite see the need to have an autoincrement ID which will require a separate index, so I am trying to make the username the Primary Key. (This will also make all references easier to decipher). Here is my User model :

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import com.fasterxml.jackson.annotation.JsonIgnore;

import lombok.Data;

@Data
@Entity
@Table(name="user")
public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -3924062441897826838L;
    @Id
    @Column(name="username")
    private String userName;
    @Column(name="password")
    private String password;
    @Column(name="role")
    private String role;
    @Column(name="first_name")
    private String firstName;
    @Column(name="last_name")
    private String lastName;
    @Column(name="country")
    private String country;
    @Column(name="enabled")
    private boolean enabled;
    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                CascadeType.PERSIST,
                CascadeType.MERGE
            },
            mappedBy = "users")
    private Set<Project> projects = new HashSet<>();
    @JsonIgnore
    @OneToMany(cascade = CascadeType.ALL,
            fetch = FetchType.LAZY,
            mappedBy = "createUser")
    private Set<Project> createdProjects = new HashSet<>();

    private User() {    }
    public User(String userName) {
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "User [userName="+ userName+",firstName="+firstName+"]";
    }


}

I can't seem to get access to my primary key (userName) through the basic routes. (this.props.user.userName... in react). I understand that it's embedded in the _links, but is there any way to access it for my list page?

**
 * User Object
 */
class User extends React.Component {

    constructor(props) {
        super(props);
        this.handleDelete = this.handleDelete.bind(this);
    }

    handleDelete() {
        this.props.onDelete(this.props.user);
    }

    render() {
        return (
          <tr>
            <td>**{this.props.user.userName} is BLANK**</td>
            <td>{this.props.user.firstName}</td>
            <td>{this.props.user.lastName}</td>
            <td>{this.props.user.enabled}</td>
            <td>
            <button onClick={this.handleDelete}>Delete</button>
        </td>
          </tr>);
      }
}

Is adding the auto increment id to User the only way? All help is greatly appreciated. Thank you!

UPDATE: Here is the output of the console.log(this.props.user) :

    Object

_links: Object

createdProjects: {href: "http://localhost:8080/api/users/testUserName/createdProjects"}

projects: {href: "http://localhost:8080/api/users/testUserName/projects"}

self: {href: "http://localhost:8080/api/users/testUserName"}

user: {href: "http://localhost:8080/api/users/testUserName"}

Object Prototype

country: "TestCountry"

enabled: true

firstName: "TestName"

lastName: "TestLastName"

password: "testPword"

role: "testrole"

Solution

  • Spring does not expose id of an entity class by default. You can configure it to expose id of a certain entity class. The code below should do the work.

    public class RestConfiguration extends RepositoryRestConfigurerAdapter {
        @Override
        public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
            config.exposeIdsFor(User.class);
        }
    }