关系型数据库其实很讨人厌,尤其是在你应用数据库驱动的开发模式时。须要首先把表给创立好了,而后再应用代码生成器反向生成一堆简直无奈可读的代码。当字段有变更的时候,又是一番折腾。
这其中的典型,就是 MyBatis,所以催生了更加简洁的 MyBatis Plus。
理解到一些大厂(阿里、腾讯、抖音等),JPA 的应用也越来越宽泛了,包含咱们公司,这是把适合的工具放到了适合的中央。如果想要疾速开发,JPA 无疑是一个比拟好的抉择。你无需关注数据库表的构造,应用代码驱动即可实现工作,管它前面是 MySQL 还是 Oracle。JPA 把数据库相干的常识给弱化了,让你专一于业务开发。
我集体曾是十分排挤 JPA 这种弱化 SQL 的工具的,这源于对早起 Hibernate 版本的错误认识。但尝试过 mybatis、spring-data-jdbc、jooq 后,发现这个货色是真的香!一个早退的赞,送给 JPA。
这对一些管理系统来说,十分适合。因为性能并不是这些零碎次要的痛点,业务复杂性才是。
本文将介绍一个简略的实体类,须要筹备哪些根本字段。这些字段,又是如何在代码中被应用的。
- 根本字段介绍
首先看一下咱们的根底定义类。
代码不多,信息却不少。
上面来一行行解析。
@Data
复制代码
Data 注解是属于 lombok 类的,lombok 是地球人都晓得的代码简化工具,提供了十分多的注解。如果你不想记忆太多的注解,间接加上一个 Data,是最偷懒的抉择。
@MappedSuperclass
复制代码
这个注解是 JPA 的,用来标识父类。标注为 @MappedSuperclass
的类将不是一个残缺的实体类,不会映射到数据库表,然而它的属性都将映射到子类的数据库字段中。放在这里再适合不过了。
@EntityListeners(AuditingEntityListener.class)
复制代码
开启主动审计性能,这个和上面的两个日期字段是相互配合的,咱们稍后介绍。
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}) // 间接应用 bean 时,防止 json 序列号失败
复制代码
有时候,咱们想要再 controller 层间接应用 JPA 的实体。但 JPA 外部其实是有很多附加变量的,比方hibernateLazyInitializer
。
为了让实体在 json 序列化的时候可能失常进行,须要疏忽这两个字段。所以这个注解,是属于 jackson json
的。
- 自定义 ID 生成器
JPA 其实提供了十分多的 ID 生成策略。不过,在互联网利用下,利用较多的还是雪花算法,因为它有着良好的扩展性,在数据迁徙的时候也不会有很多抵触。
为了指定雪花算法,咱们须要上面几行代码。
static final String ID_GEN = "cn.xjjdog.bcmall.utils.db.DistributedId";
@Id
@GenericGenerator(name = "IdGen", strategy = ID_GEN)
@GeneratedValue(generator = "IdGen")
复制代码
其中的一个要害,就是应用咱们名称叫做 IdGen
的 ID 生成器。这里的代码,是有一点小遗憾的。因为 JVM 类加载的缘故,咱们无奈在注解中间接应用类的名称(*.class.getName()
) 来获取它的包门路,只能作为字符串写死在这里。
上面咱们就来看一下这个 ID 生成器的解决。
public class DistributedId implements IdentifierGenerator {
@Override
public Serializable generate(SharedSessionContractImplementor sharedSessionContractImplementor, Object obj) throws HibernateException {if (obj == null) throw new HibernateException(new NullPointerException()) ;
if ((((AbstractEntity) obj).getId()) == null) {return String.valueOf(Snowflake.createId());
} else {return ((AbstractEntity) obj).getId();}
}
}
复制代码
代码如上。在间接应用之前,咱们还做了一点小解决。当咱们判断实体的 ID 为空的时候,才应用雪花算法结构一个新的 ID;否则应用实体原来设置好的 ID,放弃不变。
为什么这样做?因为这是有需要的。像订单这种业务,你须要学生成一个订单号,而后再更新一些数据库信息,公布一些音讯等;而不是在保留动作登程的时候才生成一个。
如果你不做下面代码的解决。JPA 将每次保留的时候都主动生成一个,笼罩了你原有的。我就在这里吃过亏,通过 debug 代码才进行的修复。
- 主动填充字段
下面说到 createdDate
和lastModifiedDate
两个字段,其实在应用的时候,是不须要手动去设值的。这两个值,将通过审计性能主动实现。
@EntityListeners(AuditingEntityListener.class)
复制代码
当然,咱们还要用特有的注解,来标识这两个字段。
/**
* 创立工夫
*/
@CreatedDate
private Date createdDate;
/**
* 更新工夫
*/
@LastModifiedDate
private Date lastModifiedDate;
复制代码
最初,不要忘了在全局配置中通过 Config 开启这个性能。
@Configuration
@EnableJpaAuditing
public class JpaConfig {
}
复制代码
当然,审计是不能没有用户的。所以这个系列还有 @CreatedBy
注解,用来标注是谁创立的。你须要在代码中组装它们,比方上面的代码,就是从 Spring Sercurity
中获取用户信息。
@Configuration
@Slf4j
public class UserAuditor implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
UserDetails user;
try {user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return Optional.ofNullable(user.getUsername());
}catch (Exception e){return Optional.empty();
}
}
}
复制代码
- End
JPA 写管理系统,真的是神器。当你不须要思考极限的代码效率时,是一个十分好的抉择。再看看最近的 MyBatis 版本,包含 MyBatis Plus 设计,很多货色曾经和 JPA 越来越像了。因为在设计上来说,JPA 是最靠近面向对象编程的思维的。
B 端简单业务的技术栈,并不需要和 C 端的技术栈相雷同。JPA 显然通过极少的代码和约定,就能把事件搞定,让开发者真正的把重点关注到业务开发上来。前面的文章,咱们还会用到 MyBatis 和 MyBatis Plus,到时候,咱们再详细分析它们应用的场景。
参考:《2020 最新 Java 根底精讲视频教程和学习路线!》
链接:https://juejin.cn/post/693856…