- 由 重写get/set 引发 JPA 的注解失效的问题
- 我写了基类 BasicsIntEntity AuditIntID BaseAuditFieldsLocalDateTime
- 在 BasicsIntEntity 中重写了 AuditIntID BaseAuditFieldsLocalDateTime 的get ```java package com.databstech.cache.jpa.entity.mysql;
import com.databstech.cache.jpa.util.TnPageUtil; import com.databstech.utils.constant.entity.groups.AuditIntID; import com.databstech.utils.constant.entity.serializable.OvSerializable; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.domain.Page; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*; import java.util.ArrayList; import java.util.Iterator; import java.util.List;
/**
- @author tn
- @version 1
- @ClassName BaseDate
- @description 公共实体INT 新建BaseDate,里面主要包含审计的公共字段,如新增人、新增时间、最后更新人、最后更新时间 *
- @EntityListeners(AuditingEntityListener.class):声明实体监听器,用于实体修改时做处理
- @MappedSuperclass:声明该类为实体父类,不会映射单独的表,而是把字段映射到子类表中
- @date 2020-09-28 16:11
*/
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@DynamicUpdate //动态赋值
@DynamicInsert //动态插入
public class BasicsIntEntity
extends AuditIntID {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(columnDefinition="int COMMENT '主键,自动生成'")
@Override
public Integer getId() {
return super.getId();
}
/**
* 表示该字段为创建时间字段,在这个实体被insert的时候,会自动为其赋值
*/
@CreatedDate
@Column(columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期' ")
@Override
public String getCreateTime() {
return super.getCreateTime();
}
/**
* 表示该字段为创建人, @CreatedBy 在这个实体被created的时候,会自动为其赋值
*/
@CreatedBy
@Column(columnDefinition = "varchar(100) COMMENT '创建人'")
@Override
public String getCreateBy() {
return super.getCreateBy();
}
/**
* 表示该字段为修改时间字段,@LastModifiedDate在这个实体被update的时候,会自动为其赋值
*/
@LastModifiedDate
@Column(columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日期'")
@Override
public String getUpdateTime() {
return super.getUpdateTime();
}
/**
* 表示该字段为修改人,@LastModifiedBy 在这个实体被update的时候,会自动为其赋值
*/
@LastModifiedBy
@Column(columnDefinition = "varchar(100) COMMENT '更新人'")
@Override
public String getUpdateBy() {
return super.getUpdateBy();
}
/**
* page
* @param page
* @param clazz
* @param <T>
* @param <S>
* @return
*/
public static <T, S extends OvSerializable> TnPageUtil<List<T>> to(Page<S> page, Class<T> clazz) {
if (page != null && !page.isEmpty()) {
List<S> content = page.getContent();
List<T> result = new ArrayList(content.size());
Iterator var3 = content.iterator();
while(var3.hasNext()) {
OvSerializable abs = (OvSerializable)var3.next();
result.add((T) abs.to(clazz));
}
return TnPageUtil.page(page.getNumber(),
page.getSize(),
page.getTotalPages(),
page.getTotalElements(),
result);
} else {
return new TnPageUtil();
}
}
}
2. 在最终使用的地方 继承 BasicsIntEntity ,结果发现本类中 @Column 出现了问题,生成不了注释
```java
package com.databstech.demo.standalone.jpa.bean;
import com.databstech.cache.jpa.entity.mysql.BasicsIntEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* @author tn
* @version 1
* @ClassName JpaDemo
* @description jpademo
* @date 2020/10/2 0:47
*/
@Entity
@Table(name ="jpa_demo",schema = "test")
@org.hibernate.annotations.Table(appliesTo = "jpa_demo",comment = "jpademo")
@Getter
@Setter
@Accessors(chain = true)
public class JpaDemo extends BasicsIntEntity<JpaDemo> {
//@Column无法生成 sql注释
@ApiModelProperty("名字")
@Column(columnDefinition = " varchar(100) not null comment '名字'" )
private String name;
@ApiModelProperty("性别")
private String sex;
// 只有这样写才能生成
@Column(name = "sex",columnDefinition="varchar(100) default '男' COMMENT '字典名'")
public String getSex() {
return sex;
}
}
- 问题原因
- jpa 的 访问策略 问题 导致的
- 我在基类中 是把注解写在 get 上的 , 所以默认整个类都使用 get 的方式为准,详情↓
- 当实体里的第一个jpa相关的注解出现在 字段 或者 get/set 方法上,就以第一次出现的方式为准!也就是说,一个实体里的注解既有用在field上面,又有用在 properties 上时,那么默认是一 field 为准,当出现在get/set方法上时就会失效!
- jpa 的 访问策略 问题 导致的
- 共存
- 使用 @Access 指定实体类的访问策略 ! 下面是 该注解的源码 ```java @Target( { TYPE, METHOD, FIELD })//表示此注解可以运用在class上(那么这个时候就可以指定此实体的默认注解生效策略了),也可以用在方法上或者字段上(表示可以独立设置某一个字段或者方法的生效策略); @Retention(RUNTIME) public @interface Access { //指定是字段上面生效还是方法上面生效 AccessType value(); } public enum AccessType { FIELD, //字段 PROPERTY //属性 get/set }
1. 实例
1. @Transient 防止二次序列化
2. @Access 类上 跟 get 上都要加
```java
# 继承类
package com.databstech.demo.standalone.jpa.bean;
import com.databstech.cache.jpa.entity.mysql.BasicsIntEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
/**
* @author tn
* @version 1
* @ClassName JpaDemo
* @description jpademo
* @date 2020/10/2 0:47
*/
@Entity
@Table(name ="jpa_demo",schema = "test")
@org.hibernate.annotations.Table(appliesTo = "jpa_demo",comment = "jpademo")
@Getter
@Setter
@Accessors(chain = true)
@DynamicUpdate //动态赋值
@DynamicInsert //动态插入
@Access(AccessType.FIELD)
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class JpaDemo extends BasicsIntEntity<JpaDemo> {
@Column(columnDefinition = " varchar(100) not null comment '名字'" )
@ApiModelProperty("名字")
private String name;
@Column(name = "sex",columnDefinition="varchar(100) default '男' COMMENT '字典名'")
@ApiModelProperty("性别")
private String sex;
// @Column(columnDefinition = " varchar(100) not null comment '名字'" )
// public String getName() {
// return name;
// }
// @Column(name = "sex",columnDefinition="varchar(100) default '男' COMMENT '字典名'")
// public String getSex() {
// return sex;
// }
}
# 基类
package com.databstech.cache.jpa.entity.mysql;
import com.databstech.cache.jpa.util.TnPageUtil;
import com.databstech.utils.constant.entity.groups.AuditIntID;
import com.databstech.utils.constant.entity.serializable.OvSerializable;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author tn
* @version 1
* @ClassName BaseDate
* @description 公共实体INT
*
*新建BaseDate,里面主要包含审计的公共字段,如新增人、新增时间、最后更新人、最后更新时间
*
* @EntityListeners(AuditingEntityListener.class):声明实体监听器,用于实体修改时做处理
* @MappedSuperclass:声明该类为实体父类,不会映射单独的表,而是把字段映射到子类表中
* @date 2020-09-28 16:11
*/
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@DynamicInsert //动态插入
@DynamicUpdate //动态赋值
@SelectBeforeUpdate
@Access(AccessType.FIELD)
public class BasicsIntEntity<T> extends AuditIntID<T> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(columnDefinition="int COMMENT '主键,自动生成'")
@Access(AccessType.PROPERTY)
@Override
public Integer getId() {
return super.getId();
}
/**
* 表示该字段为创建时间字段,在这个实体被insert的时候,会自动为其赋值
*/
@CreatedDate
@Column(columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期' ")
@Access(AccessType.PROPERTY)
@Override
public String getCreateTime() {
return super.getCreateTime();
}
/**
* 表示该字段为创建人, @CreatedBy 在这个实体被created的时候,会自动为其赋值
*/
@CreatedBy
@Column(columnDefinition = "varchar(100) COMMENT '创建人'")
@Access(AccessType.PROPERTY)
@Override
public String getCreateBy() {
return super.getCreateBy();
}
/**
* 表示该字段为修改时间字段,@LastModifiedDate在这个实体被update的时候,会自动为其赋值
*/
@LastModifiedDate
@Column(columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日期'")
@Access(AccessType.PROPERTY)
@Override
public String getUpdateTime() {
return super.getUpdateTime();
}
/**
* 表示该字段为修改人,@LastModifiedBy 在这个实体被update的时候,会自动为其赋值
*/
@LastModifiedBy
@Column(columnDefinition = "varchar(100) COMMENT '更新人'")
@Access(AccessType.PROPERTY)
@Override
public String getUpdateBy() {
return super.getUpdateBy();
}
/**
* page
* @param page
* @param clazz
* @param <T>
* @param <S>
* @return
*/
public static <T, S extends OvSerializable> TnPageUtil<List<T>> to(Page<S> page, Class<T> clazz) {
if (page != null && !page.isEmpty()) {
List<S> content = page.getContent();
List<T> result = new ArrayList(content.size());
Iterator var3 = content.iterator();
while(var3.hasNext()) {
OvSerializable abs = (OvSerializable)var3.next();
result.add((T) abs.to(clazz));
}
return TnPageUtil.page(page.getNumber(),
page.getSize(),
page.getTotalPages(),
page.getTotalElements(),
result);
} else {
return new TnPageUtil();
}
}
}
# 基类
package com.databstech.utils.constant.entity.groups;
import com.databstech.utils.constant.entity.audit.BaseAuditFieldsLocalDateTime;
import io.swagger.annotations.ApiModelProperty;
import javax.persistence.Transient;
/**
* @author tn
* @ClassName IntAudit
* @description int类型主键加审计字段
* @date 2020-09-28 15:27
*/
public class AuditIntID<T> extends BaseAuditFieldsLocalDateTime<T> {
@ApiModelProperty(value = "id")
@Transient
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}