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 {
...
}
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.
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.
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.
Method Summary Deletes the given entities in a batch which means it will create a single query. Deprecated.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With