我们正在尝试使用
Spring-Data-JPA和Spring-Data-Rest的POC.
输出看起来是例外,我们有实体字段的值,除了id,id字段在Abstract类中设置.
输出看起来是例外,我们有实体字段的值,除了id,id字段在Abstract类中设置.
我们正在使用一个简单的实体,它扩展了AbstractPersistable(它是一个spring-data-jpa类http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/domain/AbstractPersistable.html).
这是这一个的源代码:
@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; } }
和我们的实体:
@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",updatable = false) private GlobalDataType dataType; @Enumerated(EnumType.STRING) @Column(name = "VALUE_TYPE",length = 30) private ValueType valueType; @Enumerated(EnumType.STRING) @Column(name = "ATTRIBUTE_TYPE",length = 30) private AttributeType attributeType; @Column(name = "FE_DISPLAY") @Convert(converter=BooleanTFConverter.class) private Boolean feDisplay; {... getter setter equals hashcode toString ...} }
那么服务(使用spring-data-rest):
@RepositoryRestResource(path = "test") public interface TestEntityRepository extends JpaRepository<TestEntity,Long> { }
我们使用Spring启动运行应用程序Chrome上的输出(URL为http:// localhost:8080 / test)是JSON HAL数据(不显示ID !!!):
{ "_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 } }
另一件事是当我们在TestEntity(http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/domain/AbstractAuditable.html)上使用AbstractAuditable时,它可以工作,我们从AbstractAuditable获取字段值,但我们仍然没有得到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",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",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(); } }
和JSON HAL结果:
{ "_links" : { "self" : { "href" : "http://localhost:8080/test{?page,"_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,"id" : "Europe/London" },"id" : "Europe/London" },"millis" : 1412874924000,"afterNow" : false,"beforeNow" : true,"equalNow" : false },"lastModifiedBy" : null,"lastModifiedDate" : { "year" : 2014,"millisOfDay" : 65731000,"secondOfMinute" : 31,"secondOfDay" : 65731,"millis" : 1412874931000,"title" : "Test","number" : 0 } }
编辑:解决方案
添加自定义RepositoryRestMvcConfiguration
@Configuration public class MyRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration { protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.exposeIdsFor(TestEntity.class); } }
然后在您的Application java配置类中更改@import
之前:
@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 { ... }
实际:
@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 { ... }