一些问题
@Id、@CreatedDate、@LastModifiedDate注解冲突问题
Spring Data 提供了这几个方便的注解,但是在使用的过程中发现了冲突的问题,
- @Id如果使用在自定义id的字段上,比如code、name等;
- 首先如果想
@CreatedDate
、@LastModifiedDate
生效,仅在字段上加上注解时不够的,还需要在启动类Application加上注解@EnableMongoAuditing
; -
@Id
与@CreatedDate
的冲突,如果使用了@Id,那么spring-data-mongo通过调用isNew()认为在mongo中已经存在,导致@CreatedDate不会生效,而@LastModifiedDate会生效;
isNew()方法在org.springframework.data.mongodb.repository.support.SimpleMongoRepository#save
采用这种策略检查isNew()
org.springframework.data.mapping.model.PersistentEntityIsNewStrategy#isNew
解决方式
@Data
@Document(collection = "col_fund")
public class Fund extends AbstractEntity{
@Id
private String code;
private String name;
private String type;
@CreatedDate
private LocalDateTime createdDate = LocalDateTime.now();
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
这是另一种取巧的方式,不使用@CreatedDate
和@LastModifiedDate
注解,有兴趣可以看下源码
org.springframework.data.mongodb.core.MongoTemplate#doInsertBatch
@Configuration
public class MongoCreatedTimeAndLastModifiedTimeEventListener extends AbstractMongoEventListener {
@Override
public void onBeforeConvert(BeforeConvertEvent event) {
Object source = event.getSource();
if (source instanceof AbstractEntity) {
LocalDateTime now = LocalDateTime.now();
AbstractEntity entity = AbstractEntity.class.cast(source);
entity.setLastModifiedDate(now);
if (entity.getCreatedDate() == null) {
entity.setCreatedDate(now);
}
}
}
}
@Version
Long not long.
Spring-Data-Mongo 判断是否是new insert对象
org.springframework.data.mapping.model.PersistentEntityIsNewStrategy#PersistentEntityIsNewStrategy
在isNew()方法中Object value = valueLookup.apply(entity);
会根据返回的上面的策略返回Id的值或者version的值来做后续判断是否是new增加的数据。
org.springframework.data.mapping.model.PersistentEntityIsNewStrategy#isNew
总结Spring-Data 判断是否是New的依据
- 仅存在@Id时,那么如果@Id对应的字段值为null是否为空;
- 当@Id和@Version都存在时,则必须同时都有值,且version > 0 ;
- 当@Id和@Version都存在时,但只有@Version有值,报错;
this.valueType = entity.hasVersionProperty() && !idOnly // ? entity.getRequiredVersionProperty().getType() // : entity.hasIdProperty() ? entity.getRequiredIdProperty().getType() : null;
@Override public boolean isNew(Object entity) { Object value = valueLookup.apply(entity); if (value == null) { return true; } if (valueType != null && !valueType.isPrimitive()) { return value == null; } if (Number.class.isInstance(value)) { return ((Number) value).longValue() == 0; } throw new IllegalArgumentException( String.format("Could not determine whether %s is new! Unsupported identifier or version property!", entity)); }
OptimisticLockingFailureException
对重试的处理
网友评论