基于Springboot框架
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.common</groupId>
<artifactId>web-common</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
定义一个基本实体类,自动生成公用属性
/**
* 实体类继承此类
* insert操作createTime赋值为当前时间
* insert或update操作updateTime赋值为当前时间
*/
@MappedSuperclass
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private String remark; //备注
@Temporal(TemporalType.TIMESTAMP)
@UpdateTimestamp
private Date updateTime;
@Temporal(TemporalType.TIMESTAMP)
@CreationTimestamp
private Date createTime;
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
主键定义
定义Long类型主键基础类
@MappedSuperclass public abstract class LongKey extends BaseEntity{ private static final long serialVersionUID = 9134650665687245260L; @Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "jpa_sequence") @TableGenerator( name = "jpa_sequence", initialValue = 999, //初始化值 allocationSize = 1 //累加值 ) private Long id; public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
注解@GeneratedValue默认GenerationType.AUTO主键从1自增
这里使用GenerationType.TABLE规则,初始化值999,每次+1,那么主键从1000开始做为第一条数据主键自增
定义String类型主键基础类
@MappedSuperclass public abstract class StringKey extends BaseEntity{ private static final long serialVersionUID = 3151655709311338868L; @Id @Column(length = 32) private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } }
方式一:
使用uuid:
@Id
@GenericGenerator(name = "jpa-uuid", strategy = "uuid")
@GeneratedValue(generator = "jpa-uuid")
private String id;
方式二:不定义规则,采用下列方式
重写JpaRepository
public class SimpleJpaRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> {
private final JpaEntityInformation<T, ?> entityInformation;
private final EntityManager em;
public SimpleJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityInformation = entityInformation;
this.em = entityManager;
}
/**
* 保存数据
* @param entity
* @param <S>
* @return
*/
@Override
@Transactional
public <S extends T> S save(S entity) {
//获取ID
ID entityId = (ID) entityInformation.getId(entity);
Optional<T> optionalT = null;
if (StringUtils.isEmpty(entityId)) {
// 获取主键字段的属性
SingularAttribute<? super T, ?> idAttribute = entityInformation.getIdAttribute();
TypeDescriptor ptd = new BeanWrapperImpl(entity).getPropertyTypeDescriptor(idAttribute.getName());
//重写主键生成规则
if (idAttribute.getJavaType().equals(String.class)){
String key = SequentialUuidHexGenerator.generates();
new BeanWrapperImpl(entity).setPropertyValue(idAttribute.getName(), key);
}
//标记为新增数据
optionalT = Optional.empty();
} else {
//若ID非空 则查询最新数据
optionalT = findById(entityId);
}
//获取空属性的字段
String[] ignoreNullProperties = this.getNullProperties(entity);
//若根据ID查询结果为空
if (optionalT.isPresent()) {
//1.获取最新对象
T target = optionalT.get();
//2.将非空属性覆盖到最新对象
BeanUtils.copyProperties(entity, target, ignoreNullProperties);
//3.更新非空属性
em.merge(target);
return entity;
} else {
em.persist(entity);//新增
return entity;
}
}
private static String[] getNullProperties(Object src) {
//1.获取Bean
BeanWrapper srcBean = new BeanWrapperImpl(src);
//2.获取Bean的属性描述
PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
//3.获取Bean的空属性
Set<String> properties = new HashSet<>();
for (PropertyDescriptor propertyDescriptor : pds) {
String propertyName = propertyDescriptor.getName();
Object propertyValue = srcBean.getPropertyValue(propertyName);
if (null == propertyValue) { //参数值为null
//srcBean.setPropertyValue(propertyName, null);
properties.add(propertyName);
}
}
return properties.toArray(new String[properties.size()]);
}
}
String key = SequentialUuidHexGenerator.generates();
主键生成方式可以自定义选择
这里采用的uuid有序生成工具参考Java 生成有序 UUID - VictorBu - 博客园
重写了save中的更新规则,过滤null值,避免更新部分字段时导致其他字段赋空