Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't get the JPA entity ID in the JSON output

We are trying a POC with Spring-Data-JPA and Spring-Data-Rest. The output looks as excepted, we have the values of our entity fields except for the id, the id field is set in an Abstract class.

We are using a simple entity witch extends of AbstractPersistable (it's a spring-data-jpa class http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/domain/AbstractPersistable.html).

Here the source code of this one:

@MappedSuperclass
public abstract class AbstractPersistable<PK extends Serializable> implements Persistable<PK> {

    private static final long serialVersionUID = -5554308939380869754L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private PK id;

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.domain.Persistable#getId()
     */
    public PK getId() {

        return id;
    }

    /**
     * Sets the id of the entity.
     * 
     * @param id the id to set
     */
    protected void setId(final PK id) {

        this.id = id;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.domain.Persistable#isNew()
     */
    public boolean isNew() {

        return null == getId();
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {

        return String.format("Entity of type %s with id: %s", this.getClass().getName(), getId());
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {

        if (null == obj) {
            return false;
        }

        if (this == obj) {
            return true;
        }

        if (!getClass().equals(obj.getClass())) {
            return false;
        }

        AbstractPersistable<?> that = (AbstractPersistable<?>) obj;

        return null == this.getId() ? false : this.getId().equals(that.getId());
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {

        int hashCode = 17;

        hashCode += null == getId() ? 0 : getId().hashCode() * 31;

        return hashCode;
    }
}

and our entity:

@Entity
@Table(name = "TEST_ENTITY")
public class TestEntity extends AbstractPersistable<Long> {

    @Column(name = "TITLE", nullable = false, length = 100)
    private String title;

    @Column(name = "DESCRIPTION", length = 500)
    private String description;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "GLOBAL_DATATYPE_ID", referencedColumnName = "ID", nullable = false, updatable = false)
    private GlobalDataType dataType;

    @Enumerated(EnumType.STRING)
    @Column(name = "VALUE_TYPE", nullable = false, length = 30)
    private ValueType valueType;

    @Enumerated(EnumType.STRING)
    @Column(name = "ATTRIBUTE_TYPE", nullable = false, length = 30)
    private AttributeType attributeType;

    @Column(name = "FE_DISPLAY")
    @Convert(converter=BooleanTFConverter.class)
    private Boolean feDisplay;

 {... getter setter equals hashcode toString ...}
}

then the the service (using spring-data-rest):

@RepositoryRestResource(path = "test")
public interface TestEntityRepository extends JpaRepository<TestEntity, Long> {
}

We run the app with Spring boot And the output on Chrome (URL is http://localhost:8080/test) is a JSON + HAL data (the id is not displayed !!!):

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/test{?page,size,sort}",
      "templated" : true
    }
  },
  "_embedded" : {
    "testEntities" : [ {
      "title" : "Test",
      "description" : "TEST",
      "valueType" : "SINGLE",
      "attributeType" : "ATTRIBUTE",
      "feDisplay" : true,
      "new" : false,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/test/1"
        },
        "dataType" : {
          "href" : "http://localhost:8080/test/1/dataType"
        }
      }
    } ]
  },
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

And another thing is when we use AbstractAuditable on the TestEntity (http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/domain/AbstractAuditable.html), it works, we get the fields values from AbstractAuditable but we still don't get the id...

@Entity
@Table(name = "TEST_ENTITY")
public class TestEntity  extends AbstractAuditable<User, Long> {
...
}

@MappedSuperclass
public abstract class AbstractAuditable<U, PK extends Serializable> extends AbstractPersistable<PK> implements
        Auditable<U, PK> {

    private static final long serialVersionUID = 141481953116476081L;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "CREATED_BY", referencedColumnName = "ID", nullable = false, updatable = false)
    private U createdBy;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATED_DATE")
    private Date createdDate;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "LAST_MODIFIED_BY", referencedColumnName = "ID", nullable = false, updatable = false)
    private U lastModifiedBy;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "LAST_MODIFIED_DATE")
    private Date lastModifiedDate;

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.domain.Auditable#getCreatedBy()
     */
    public U getCreatedBy() {

        return createdBy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.data.domain.Auditable#setCreatedBy(java.lang.Object)
     */
    public void setCreatedBy(final U createdBy) {

        this.createdBy = createdBy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.domain.Auditable#getCreatedDate()
     */
    public DateTime getCreatedDate() {

        return null == createdDate ? null : new DateTime(createdDate);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.data.domain.Auditable#setCreatedDate(org.joda.time
     * .DateTime)
     */
    public void setCreatedDate(final DateTime createdDate) {

        this.createdDate = null == createdDate ? null : createdDate.toDate();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.domain.Auditable#getLastModifiedBy()
     */
    public U getLastModifiedBy() {

        return lastModifiedBy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.data.domain.Auditable#setLastModifiedBy(java.lang
     * .Object)
     */
    public void setLastModifiedBy(final U lastModifiedBy) {

        this.lastModifiedBy = lastModifiedBy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.domain.Auditable#getLastModifiedDate()
     */
    public DateTime getLastModifiedDate() {

        return null == lastModifiedDate ? null : new DateTime(lastModifiedDate);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.data.domain.Auditable#setLastModifiedDate(org.joda
     * .time.DateTime)
     */
    public void setLastModifiedDate(final DateTime lastModifiedDate) {

        this.lastModifiedDate = null == lastModifiedDate ? null : lastModifiedDate.toDate();
    }
}

And JSON+HAL result:

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/test{?page,size,sort}",
      "templated" : true
    }
  },
  "_embedded" : {
    "testEntities" : [ {
      "createdBy" : {
        "username" : "xxx.admin"
      },
      "createdDate" : {
        "year" : 2014,
        "era" : 1,
        "dayOfYear" : 282,
        "dayOfWeek" : 4,
        "dayOfMonth" : 9,
        "weekOfWeekyear" : 41,
        "monthOfYear" : 10,
        "yearOfEra" : 2014,
        "yearOfCentury" : 14,
        "centuryOfEra" : 20,
        "weekyear" : 2014,
        "millisOfSecond" : 0,
        "millisOfDay" : 65724000,
        "secondOfMinute" : 24,
        "secondOfDay" : 65724,
        "minuteOfHour" : 15,
        "minuteOfDay" : 1095,
        "hourOfDay" : 18,
        "chronology" : {
          "zone" : {
            "fixed" : false,
            "uncachedZone" : {
              "cachable" : true,
              "fixed" : false,
              "id" : "Europe/London"
            },
            "id" : "Europe/London"
          }
        },
        "zone" : {
          "fixed" : false,
          "uncachedZone" : {
            "cachable" : true,
            "fixed" : false,
            "id" : "Europe/London"
          },
          "id" : "Europe/London"
        },
        "millis" : 1412874924000,
        "afterNow" : false,
        "beforeNow" : true,
        "equalNow" : false
      },
      "lastModifiedBy" : null,
      "lastModifiedDate" : {
        "year" : 2014,
        "era" : 1,
        "dayOfYear" : 282,
        "dayOfWeek" : 4,
        "dayOfMonth" : 9,
        "weekOfWeekyear" : 41,
        "monthOfYear" : 10,
        "yearOfEra" : 2014,
        "yearOfCentury" : 14,
        "centuryOfEra" : 20,
        "weekyear" : 2014,
        "millisOfSecond" : 0,
        "millisOfDay" : 65731000,
        "secondOfMinute" : 31,
        "secondOfDay" : 65731,
        "minuteOfHour" : 15,
        "minuteOfDay" : 1095,
        "hourOfDay" : 18,
        "chronology" : {
          "zone" : {
            "fixed" : false,
            "uncachedZone" : {
              "cachable" : true,
              "fixed" : false,
              "id" : "Europe/London"
            },
            "id" : "Europe/London"
          }
        },
        "zone" : {
          "fixed" : false,
          "uncachedZone" : {
            "cachable" : true,
            "fixed" : false,
            "id" : "Europe/London"
          },
          "id" : "Europe/London"
        },
        "millis" : 1412874931000,
        "afterNow" : false,
        "beforeNow" : true,
        "equalNow" : false
      },
      "title" : "Test",
      "description" : "TEST",
      "valueType" : "SINGLE",
      "attributeType" : "ATTRIBUTE",
      "feDisplay" : true,
      "new" : false,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/test/1"
        },
        "dataType" : {
          "href" : "http://localhost:8080/test/1/dataType"
        }
      }
    } ]
  },
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

EDIT: Solution

Add a custom RepositoryRestMvcConfiguration

@Configuration
public class MyRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {

    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(TestEntity.class);
    }
}

Then change in your Application java config class the @import

Before:

@Configuration
@EnableTransactionManagement
@Import(RepositoryRestMvcConfiguration.class)
@EnableJpaRepositories(basePackages="uk.co.xxx.marketplace.data.repository")
@PropertySources({@PropertySource("classpath:hibernate.properties"),@PropertySource("classpath:persistence.properties")})
@ComponentScan(value = "uk.co.xxx.marketplace.data")
@EnableAutoConfiguration
public class Application {
...
}

Actual:

@Configuration
@EnableTransactionManagement
@Import(MyRepositoryRestMvcConfiguration.class)
@EnableJpaRepositories(basePackages="uk.co.xxx.marketplace.data.repository")
@PropertySources({@PropertySource("classpath:hibernate.properties"),@PropertySource("classpath:persistence.properties")})
@ComponentScan(value = "uk.co.xxx.marketplace.data")
@EnableAutoConfiguration
public class Application {
...
}
like image 963
Emilien Brigand Avatar asked Oct 10 '14 09:10

Emilien Brigand


People also ask

How do I find JPA ID?

To find entity by their ID, we use the EntityManager. find() method and pass the entity class and the entity ID as the parameters. In the code snippet below the EntityManager required by the ArtistDaoImpl will be passed from the main program when the DAO is instantiated.

Does JPA need ID?

The Id Annotation. Each JPA entity must have a primary key that uniquely identifies it. The @Id annotation defines the primary key. We can generate the identifiers in different ways, which are specified by the @GeneratedValue annotation.

How do I enable JPA?

If we want to use JPA with MySQL database, we need the mysql-connector-java dependency. We'll also need to define the DataSource configuration. We can do this in a @Configuration class or by using standard Spring Boot properties. Spring Boot will automatically configure a data source based on these properties.

Is JpaRepository deprecated?

Method Summary Deletes the given entities in a batch which means it will create a single query. Deprecated.


1 Answers

You can subclass the class RepositoryRestConfiguration (or RepositoryRestMVCConfiguration, if using Spring MVC), and call the method exposeIdsFor() with your domain classes, for which you want to expose the ids.

like image 140
dunni Avatar answered Oct 17 '22 03:10

dunni