浅谈 Code First or DB First,JPA or Mybatis

Updated on in Java with 694 views and 1 comments

Code First or DB First,这个问题我也一直在思考,知乎上也有各种解答,有说这个好的也有说另一个好的。

概要

首先介绍一下这两种开发方案:

  • Code First:即先编写模型代码,后通过代码生成数据库表结构
  • DB First:即先创建数据库表结构,通过表结构生成代码

其实这两种方案都有各自的优点,并且我发现,这两种方式其实拿不同的 ORM 框架有不同的最佳选择。

优点

  • Code First:更符合面向对象的开发思路,适于敏捷开发
  • DB First:在有很好的数据库设计的前提下,特别是连表关系,适用该模式开发

其实还有一种 Model First 开发模式,其实质也是在没有创建数据库前提下,通过IDE等工具生成的数据库表结构,这里不在展开,可以直接以 Code First 模式为例。

如何选择

说了那么多,还是没有讲怎么选择。其实上面已经提到了,要根据不同的 ORM 框架选择最佳的,这也是我根据经验所总结的。

那 Python Flask 为例,在生产开发中其实通常会用 Flask-Migrate,通过它将 Code 转换为数据库表结构会非常的方便,所以豪无疑问,选择 Code First 开发模式效率会更加,包括 Python Django Migration,不仅能很好的生成数据库表结构,还能对每一次迁移变更做记录,选择 Code First 也豪无疑问。

以下是拿 Python Flask 模型代码的举例,其中定义了很多 Column 对象,相当于表结构中的列,并且指定了字段的许多属性,如长度,唯一索引,是否为 Null 等。

class User(BaseModel):
    """
    用户模型
    """
    __tablename__ = 'user'

    username = Column(String(32), unique=True, nullable=False, comment='用户名', index=True)
    _password = Column('password', String(128), nullable=False, comment='密码')
    nickname = Column(String(32), comment='昵称')
    mobile = Column(String(16), comment='手机号')
    avatar = Column(String(256), comment='头像')
    age = Column(Integer, comment='年龄')

JPA or Mybatis

那在 Java 开发中又应当怎么选择呢,这就需要拿 Java 主流的两个 ORM 框架来讲了 JPA、Mybatis,我相信现在很多应该不用 Hibernate 了吧(doge)。

JPA

首先来说一下 JPA,它是 Spring Data 官方的持久化框架,通常说的 JPA 一般就是指代 Spring Data JPA,它能通过拼接语法关键字来实现数据库查询,所以查询起来相对方便,但方法名可能会很长。

目前,国外很多企业还是以使用 JPA 开发为主,虽然 JPA 在连表查询效率不见得很高,但 JPA 开发效率高,且国外受人口因素影响,大数据量项目会国内少很多。

网上找的 JPA 支持的关键字如下表所示:

Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike ... findByFirstnameNotLike
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

JPA 也是支持 Code First 模式的,在 Spring-Boot 开发时,通过 @Entity 注解可以将实体标注为一个数据库表结构,并在配置文件中通过 ddl-auto 属性指定是否生成数据库结构。

以下代码是 JPA 定义的模型结构:

@Data
@Entity
@Table(name = "user")
public class User{
	@Id
	@Column(name = "id")
	private Long id;

	@Column(name = "name", length=50, nullable=true)
	private String name;
	
	@Column(name = "age")
	private Integer age;
	
	@Column(name = "birthday")
	private Date birthday;
}

JPA 通过 @Column 注解添加对数据库列属性的描述,但在多表关联时,还需要配置外键关联的导航属性(当然这不是必须的,只有业务需要时配置),虽然强外键不是一种很好的办法。无论是查询还是创建表,JPA 在单表上的使用优势很大,但在多表联合时开发成本相对增加。

所以,在使用 JPA 开发时,用 Code First 适合表结构相对独立的情况。

Mybatis

Mybatis 上面说到了,国内用的居多,其实也是因为潮流导致的,其实 80%-90% 用 JPA 一定是可以解决的,但大家都跟着卷,才有了目前的情况。

好在 Mybatis 有增强插件 Mybatis-Plus,在使用 Mybatis 时需要配置 XML 和编写 SQL,但 Mybatis-Plus 使用注解都能很好的解决,也支持了许多常用的查询方法,使用起来的已经和 JPA 一样方便了。

那使用 Mybatis-Plus 时是用哪种开发模式最优呢?个人认为使用 Mybatis-Plus 应该选择 DB First 更为合适,因为 Mybatis-Plus 提供的代码生成器,不仅能根据数据库表结构生成模型代码,同时还能生成 Mapper、Service、Controller,简直是 CRUD 工程师的福星,开发人员只需要专注开发业务代码即可,当然你也可以只用它来生成的 Model 模型代码。

总结

对于 Code First or DB First 很多时候也是见仁见智吧,或许对于其他开发者还有更好的方案,以上的思路只是我针对不同开发框架下的个人选择。

综上,不难看出,我通常在使用 Python 开发时,选择 Code First,而在 Java 开发时,选择 DB First。最后说一下选择 JPA 还是 Mybatis 的问题。在国内大背景下,受 “剧场效应” 的影响,我们不得不做一个站着看剧的观众,当然掌握多种技术亦是最佳选择,以防被社会的大潮流清洗淘汰。


标题:浅谈 Code First or DB First,JPA or Mybatis
作者:Jeffrey

Responses
取消