实体公共抽象类如下:
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* entity 抽象类
*/
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AbstractEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
protected Integer id;
@Column(nullable = false)
@Version
protected Integer jpaVersion;
@CreatedDate
protected Date createdDate;
@LastModifiedDate
protected Date lastModifiedDate;
public Integer getId() {
return id;
}
public Integer getJpaVersion() {
return jpaVersion;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public Date getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
这个问题排查了许久,找到了 jpa 给 加了 @version 注解的 version 字段添加默认值的地方。
根据 persist 方法的大致查询链路,可以看到 version 字段是有值的。
persist:
org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(Object entity) -->
org.hibernate.internal.SessionImpl.persist(Object object) -->
org.hibernate.internal.SessionImpl.onPersist(PersistEvent event, Map createCache)
// 这里就不描述具体的实现细节啦,因为我确实读不懂呀
执行的 sql 也打印出来,发现 自定义的 jpaVersion 是值的。
到了这里,百思不得其解。但是真实原因却超级简单,是一个小细节。
这里有一个很不好的习惯,使用@Column 的时候,没有定义 字段的名称。 基本应该都明白了吧
没错,就是犯了一个超级低级的错误,由于之前使用的 hibernate4 , 配置的命名策略是:
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
这种配置情况下,表明和 字段名如果不设置的话,会自动生成 xx_xx 这种的。后面 升级了 hibernate5,之前的配置就不生效了,表里生成了 这种驼峰式的字段。后面重新添加了配置,但是表里面已经生成了驼峰式的字段没有删除。所以这里的报错是 驼峰式的非空字段没有数值。删除 驼峰式的字段就可以了。