以前做学校里的项目时强推了一把 Play Framework,鼓吹它有多么多么轻量,它用JPA做ORM是多么方便,可参考以前的文章 JPA泛型DAO 和 mooctest项目总结。直到今天踩到了个坑。。。记录下JPA中坑爹的ddl
参数
JPA
JPA全称为:Java Persistence API。JPA通过Java中的 Annotation 或 XML 来描述“对象-关系表”的映射关系,并将运行期的实体对象持久化到数据库中。这是查自百度的解释,可简单理解为就是Java小组为 ORM(Object Relational Mapping) 定了一套接口规范,我们常见的 Hibernate 和 Spring 中的ORM都可理解为是 JPA 的一种具体实现。(各框架对接口规范的实现程度和匹配度可能并不完全。。。)
Play中的JPA
在Play Framework 1.2.7中,其JPA底层采用的是 Hibernate 3.6 的实现。在Play的application.conf
文件中可以看到有如下一段配置说明:
1 | # Specify the ddl generation pattern to use. Set to none to disable it |
在调试模式下,jpa.default.ddl
的默认值就是update
。。。那到底什么是ddl
呢,坑又是啥?
ddl
DDL的全称为:Data Definition Language,大概是学数据库课或集成软件开发的时候见过这类的词汇,大概就是数据库中定义数据结构的方式。我查到一个eclipse里的JPA工具里有这么一段:
Use
eclipselink.ddl-generation
to specify how EclipseLink generates DDL (Data Definition Language) for the database schema (tables and constraints) on deployment.
EclipseLink也是一套支持JPA的ORM方案,然而我并没有使用过。。。看名字应该是eclipse的官方组织搞的,但网上说由于文档较少,并不推荐。。
回到上面那段定义,我理解的JPA中ddl的过程如下
- 读取实体对象类中 Java Annotation 对属性的定义
- 生成 DDL 的描述文件
- 根据具体数据库的dialect,生成 schema 的SQL语句
- 在数据库中生成对应的schema
所以坑是
上述 ddl 的好处在于,当项目刚构建时,或在本地开发新模块时,我们可以先定义实体对象的类,通过 Java Annotation 配置字段和实体对象关系,ddl 可以帮我们自动生成相应的数据库表。这是非常便捷的,因为刚开发时实体对象的属性可能会经常调整,ddl 可以在每次运行项目时自动将这些变化同步到数据库中。
所以回过头再看Play中的那段配置
1 | # Specify the ddl generation pattern to use. Set to none to disable it |
所以在开发状态下,ddl可以默认开启,以省去我们手动修改数据库字段的活儿。。而当生产状态下,最好不要开启该 ddl generation 功能!
下面是重点,我的坑在于,我在本地开发状态下,图省事直接让项目连接了服务器上的数据库
结果就是我还处于 DEV 状态,然而默认jpa.default.ddl=update
,当我增加实体对象类中的属性时,就会帮我重新 build 一遍 schema,服务器上我亲手建的数据表里的字段类型和外键索引都乱了。。。最后我把jpa.default.ddl=none
加上了
教训
- 本地开发时禁止连接服务器数据库
- 不要使用 ddl 生成的数据库表,字段类型和外键名很丑,反正最后还得手动调
- 希望是先手动建表,然后可以使用类似 hibernate 中逆向工程的那种工具将表结构反射到对象class