Code First or DB First,这个问题我也一直在思考,知乎上也有各种解答,有说这个好的也有说另一个好的。
首先介绍一下这两种开发方案:
其实这两种方案都有各自的优点,并且我发现,这两种方式其实拿不同的 ORM 框架有不同的最佳选择。
其实还有一种 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='年龄')
那在 Java 开发中又应当怎么选择呢,这就需要拿 Java 主流的两个 ORM 框架来讲了 JPA、Mybatis,我相信现在很多应该不用 Hibernate 了吧(doge)。
首先来说一下 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 上面说到了,国内用的居多,其实也是因为潮流导致的,其实 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 的问题。在国内大背景下,受 “剧场效应” 的影响,我们不得不做一个站着看剧的观众,当然掌握多种技术亦是最佳选择,以防被社会的大潮流清洗淘汰。
博客新换的皮肤