如何在 Jhipster 生成的应用程序上从 AbstractAuditingEntity 扩展实体?
How to extend Entity from AbstractAuditingEntity on Jhipster generated app?
我使用命令 yo jhipster:entity MyEntity
生成了一个实体(我使用的是 generator-jhipster@2.19.0 )
和以下选项
{
"relationships": [],
"fields": [
{
"fieldId": 1,
"fieldName": "title",
"fieldType": "String"
}
],
"changelogDate": "20150826154353",
"dto": "no",
"pagination": "no"
}
我在 liquibase 更新日志文件中添加了可审核的列
<changeSet id="20150826154353" author="jhipster">
<createSequence sequenceName="SEQ_MYENTITY" startValue="1000" incrementBy="1"/>
<createTable tableName="MYENTITY">
<column name="id" type="bigint" autoIncrement="${autoIncrement}" defaultValueComputed="SEQ_MYENTITY.NEXTVAL">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="title" type="varchar(255)"/>
<!--auditable columns-->
<column name="created_by" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="created_date" type="timestamp" defaultValueDate="${now}">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="varchar(50)"/>
<column name="last_modified_date" type="timestamp"/>
</createTable>
</changeSet>
并修改 MyEntity class 以扩展 AbstractAuditingEntity
@Entity
@Table(name = "MYENTITY")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity extends AbstractAuditingEntity implements Serializable {
然后 运行 mvn test
得到以下异常
[DEBUG] com.example.web.rest.MyEntityResource - REST request to update MyEntity : MyEntity{id=2, title='UPDATED_TEXT'}
javax.validation.ConstraintViolationException: Validation failed for classes [com.example.domain.MyEntity] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=createdBy, rootBeanClass=class com.example.domain.MyEntity, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:160)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreUpdate(BeanValidationEventListener.java:103)
at org.hibernate.action.internal.EntityUpdateAction.preUpdate(EntityUpdateAction.java:257)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:134)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:67)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1191)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1257)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449)
at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:67)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:318)
这是失败的测试
@Test
@Transactional
public void updateMyEntity() throws Exception {
// Initialize the database
myEntityRepository.saveAndFlush(myEntity);
int databaseSizeBeforeUpdate = myEntityRepository.findAll().size();
// Update the myEntity
myEntity.setTitle(UPDATED_TITLE);
restMyEntityMockMvc.perform(put("/api/myEntitys")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(myEntity)))
.andExpect(status().isOk());
// Validate the MyEntity in the database
List<MyEntity> myEntitys = myEntityRepository.findAll();
assertThat(myEntitys).hasSize(databaseSizeBeforeUpdate);
MyEntity testMyEntity = myEntitys.get(myEntitys.size() - 1);
assertThat(testMyEntity.getTitle()).isEqualTo(UPDATED_TITLE);
}
抛出异常的行是这个
List<MyEntity> myEntitys = myEntityRepository.findAll();
我注意到 TestUtil.convertObjectToJsonBytes(myEntity)
方法正在返回没有可审计属性的 JSON 对象表示 - 这是预期的,因为 @JsonIgnore 注释 - 但我想 mockMVC.perform 更新操作不遵守在 createdBy 字段
上设置的 updatable = false
属性
@CreatedBy
@NotNull
@Column(name = "created_by", nullable = false, length = 50, updatable = false)
@JsonIgnore
private String createdBy;
如何使实体可审核并通过测试?
问题是 transferred (serialized) objects 不包含可审核的属性(由于 @JsonIgnore 注释),这与 @NotNull 注释相结合产生ConstraintViolation.
1.- 一种解决方案是 首先检索 object 我们要更新的字段,然后仅更新您需要的字段。 因此,在我们的示例中我们需要修改 MyEntityResource class 上的更新方法,如下所示:
/**
* PUT /myEntitys -> Updates an existing myEntity.
*/
@RequestMapping(value = "/myEntitys",
method = RequestMethod.PUT,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<MyEntity> update(@RequestBody MyEntity myEntityReceived) throws URISyntaxException {
log.debug("REST request to update MyEntity : {}", myEntityReceived);
if (myEntityReceived.getId() == null) {
return create(myEntityReceived);
}
MyEntity myEntity = myEntityRepository.findOne(myEntityReceived.getId());
myEntity.setTitle(myEntityReceived.getTitle());
MyEntity result = myEntityRepository.save(myEntity);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert("myEntity", myEntity.getId().toString()))
.body(result);
}
2.- 另一种解决方案是通过删除 AbstractAuditingEntity 中所需值的 @JsonIgnore 注释 来包含可审计字段。
创建实体时会产生如下响应
{
"createdBy":"admin",
"createdDate":"2015-08-27T17:40:20Z",
"lastModifiedBy":"admin",
"lastModifiedDate":"2015-08-27T17:40:20Z",
"id":1,
"title":"New Entity"
}
因此,在更新实体时,请求将包含之前生成的值
{
"createdBy":"admin",
"createdDate":"2015-08-27T17:40:20Z",
"lastModifiedBy":"admin",
"lastModifiedDate":"2015-08-27T17:40:20Z",
"id":1,
"title":"New Entity Updated"
}
同样更新响应,但是更新了 lastModified 字段
{
"createdBy":"admin",
"createdDate":"2015-08-27T17:40:20Z",
"lastModifiedBy":"admin",
"lastModifiedDate":"2015-08-27T17:45:12Z",
"id":1,
"title":"New Entity Updated"
}
两种解决方案各有优缺点,因此请选择最适合您的解决方案。
此外,您应该在 generator-jhipster 上查看此 issue,虽然它只是标题为 DTO 实体,但无论您是否使用它们都是同样的问题。
正如我在与 JHipster 相关的一些问题上发现的(现在找不到我要引用的页面)最好和最简单的解决方案(在我看来)是这个包
for applying audit on generated entities .
它包含您需要的一切,它还会更改更改日志文件并在数据库中生成列:created_by
、created_date
、last_modified_by
和 last_modified_date
。
此致
我使用命令 yo jhipster:entity MyEntity
生成了一个实体(我使用的是 generator-jhipster@2.19.0 )
和以下选项
{
"relationships": [],
"fields": [
{
"fieldId": 1,
"fieldName": "title",
"fieldType": "String"
}
],
"changelogDate": "20150826154353",
"dto": "no",
"pagination": "no"
}
我在 liquibase 更新日志文件中添加了可审核的列
<changeSet id="20150826154353" author="jhipster">
<createSequence sequenceName="SEQ_MYENTITY" startValue="1000" incrementBy="1"/>
<createTable tableName="MYENTITY">
<column name="id" type="bigint" autoIncrement="${autoIncrement}" defaultValueComputed="SEQ_MYENTITY.NEXTVAL">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="title" type="varchar(255)"/>
<!--auditable columns-->
<column name="created_by" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="created_date" type="timestamp" defaultValueDate="${now}">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="varchar(50)"/>
<column name="last_modified_date" type="timestamp"/>
</createTable>
</changeSet>
并修改 MyEntity class 以扩展 AbstractAuditingEntity
@Entity
@Table(name = "MYENTITY")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity extends AbstractAuditingEntity implements Serializable {
然后 运行 mvn test
得到以下异常
[DEBUG] com.example.web.rest.MyEntityResource - REST request to update MyEntity : MyEntity{id=2, title='UPDATED_TEXT'}
javax.validation.ConstraintViolationException: Validation failed for classes [com.example.domain.MyEntity] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=createdBy, rootBeanClass=class com.example.domain.MyEntity, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:160)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreUpdate(BeanValidationEventListener.java:103)
at org.hibernate.action.internal.EntityUpdateAction.preUpdate(EntityUpdateAction.java:257)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:134)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:67)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1191)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1257)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449)
at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:67)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:318)
这是失败的测试
@Test
@Transactional
public void updateMyEntity() throws Exception {
// Initialize the database
myEntityRepository.saveAndFlush(myEntity);
int databaseSizeBeforeUpdate = myEntityRepository.findAll().size();
// Update the myEntity
myEntity.setTitle(UPDATED_TITLE);
restMyEntityMockMvc.perform(put("/api/myEntitys")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(myEntity)))
.andExpect(status().isOk());
// Validate the MyEntity in the database
List<MyEntity> myEntitys = myEntityRepository.findAll();
assertThat(myEntitys).hasSize(databaseSizeBeforeUpdate);
MyEntity testMyEntity = myEntitys.get(myEntitys.size() - 1);
assertThat(testMyEntity.getTitle()).isEqualTo(UPDATED_TITLE);
}
抛出异常的行是这个
List<MyEntity> myEntitys = myEntityRepository.findAll();
我注意到 TestUtil.convertObjectToJsonBytes(myEntity)
方法正在返回没有可审计属性的 JSON 对象表示 - 这是预期的,因为 @JsonIgnore 注释 - 但我想 mockMVC.perform 更新操作不遵守在 createdBy 字段
updatable = false
属性
@CreatedBy
@NotNull
@Column(name = "created_by", nullable = false, length = 50, updatable = false)
@JsonIgnore
private String createdBy;
如何使实体可审核并通过测试?
问题是 transferred (serialized) objects 不包含可审核的属性(由于 @JsonIgnore 注释),这与 @NotNull 注释相结合产生ConstraintViolation.
1.- 一种解决方案是 首先检索 object 我们要更新的字段,然后仅更新您需要的字段。 因此,在我们的示例中我们需要修改 MyEntityResource class 上的更新方法,如下所示:
/**
* PUT /myEntitys -> Updates an existing myEntity.
*/
@RequestMapping(value = "/myEntitys",
method = RequestMethod.PUT,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<MyEntity> update(@RequestBody MyEntity myEntityReceived) throws URISyntaxException {
log.debug("REST request to update MyEntity : {}", myEntityReceived);
if (myEntityReceived.getId() == null) {
return create(myEntityReceived);
}
MyEntity myEntity = myEntityRepository.findOne(myEntityReceived.getId());
myEntity.setTitle(myEntityReceived.getTitle());
MyEntity result = myEntityRepository.save(myEntity);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert("myEntity", myEntity.getId().toString()))
.body(result);
}
2.- 另一种解决方案是通过删除 AbstractAuditingEntity 中所需值的 @JsonIgnore 注释 来包含可审计字段。
创建实体时会产生如下响应
{
"createdBy":"admin",
"createdDate":"2015-08-27T17:40:20Z",
"lastModifiedBy":"admin",
"lastModifiedDate":"2015-08-27T17:40:20Z",
"id":1,
"title":"New Entity"
}
因此,在更新实体时,请求将包含之前生成的值
{
"createdBy":"admin",
"createdDate":"2015-08-27T17:40:20Z",
"lastModifiedBy":"admin",
"lastModifiedDate":"2015-08-27T17:40:20Z",
"id":1,
"title":"New Entity Updated"
}
同样更新响应,但是更新了 lastModified 字段
{
"createdBy":"admin",
"createdDate":"2015-08-27T17:40:20Z",
"lastModifiedBy":"admin",
"lastModifiedDate":"2015-08-27T17:45:12Z",
"id":1,
"title":"New Entity Updated"
}
两种解决方案各有优缺点,因此请选择最适合您的解决方案。
此外,您应该在 generator-jhipster 上查看此 issue,虽然它只是标题为 DTO 实体,但无论您是否使用它们都是同样的问题。
正如我在与 JHipster 相关的一些问题上发现的(现在找不到我要引用的页面)最好和最简单的解决方案(在我看来)是这个包 for applying audit on generated entities .
它包含您需要的一切,它还会更改更改日志文件并在数据库中生成列:created_by
、created_date
、last_modified_by
和 last_modified_date
。
此致