一、问题
如果你开发了service-builder类型的项目(我肯定你一定会开发这种类型的项目),其中所使用的业务实体的数据库表结构就在service.xml中配置,然后执行build-service生成相关dao层的代码(不清楚dao的概念的参考这篇文章),然后部署项目,portal就会自动执行创建数据库表的sql语句。在62开发中,修改service.xml后,执行build-service,部署项目,portal会根据表结构的变化帮你自动修改数据里面的表,并且尽可能保留数据(我试过,增加字段没问题,其他忘了)。
以上是一些背景知识,但是在dxp开发中,根据所谓的数据库保护机制,即使我们在service.xml中修改了表结构,重新部署项目时,portal不会帮我们修改数据库表结构,即使在开发阶段也是如此。如果你想让portal修改表结构,你就要按照这篇文章的方式来做,即:每次修改表结构,就要写对应的数据库升级语句,由于过程比较复杂,我一直没按照文章操作,看着就头晕,不过是为了修改数据库表结构,为何要我写额外的代码?于是我研究了lifeay执行tables.sql的过程,发现了强制让portal执行tables.sql的方法。
二 、解决方案
首先我只是说出方法,让着急使用的人直接使用,然后我再分享研究过程。
前提:portal是连接mysql启动的
方法:
1. 修改service.xml,运行build-service
2. 连接mysql数据库,找到servicecomponent表,删除里面namespace的值和你的service.xml中namespace值相同的所有数据
3. 同时删除service.xml对对应的已经创建的所有表
4. 在Server Administrator里面执行Verify database tables of all plugins
5. 部署项目,portal会重新执行tables.sql,表就重新建立了
(补充:部署项目后,看到输出了"Running xxxx SQL scripts",但是数据库中还是没有表,这时再次执行Verify database tables of all plugins就可以在数据库看到表了)
三、研究过程
接下来我分享一下研究过程:
我们可能注意到了,部署一个新service-builder类型的项目时,控制台会输出一个语句 "Running xxxx SQL scripts",在portal源码中搜索“SQL scripts”,找到了在ServiceComponentLocalServiceImpl.java类里面,
如果是已经部署过的项目,再次部署,只会看到“Upgrading xxxx database to build number ?”之类的信息,说明数据库中一定有表记录着哪些项目部署过,buildnumber是多少,于是我们找到了servicecomponent表,查看数据,正好有我们用过的namespace,删除这些数据,重新部署项目,发现并不能执行tables.sql文件,我们猜测可能内存中存在某些缓存记录这些数据,于是执行了Verify database tables of all plugins,再次部署,终于能执行tables.sql了。ServiceComponentLocalServiceImpl.java是比较核心的类,如果仔细研究这个类的代码会有其他收获,这里只列举一个例子:
大家可以看到这个类其实支持升级数据库的操作,只要之前的tablesql和新的tablesql不一致时,会执行升级数据库操作,按照我们的思路,我们两次部署的tables.sql是不一致的,为什么不执行这段代码呢?调试发现tablessql变量始终为空字符串(不是null,是值为“”的字符串),所以永远不会执行升级数据库操作,servicecomponent表的CDATA字段也能看出,dxp不会记录tables.sql语句。至于为什么执行Verify database tables of all plugins,才能重新执行,我没有再往下研究了,参考EditServerMVCActionCommand.java中的verifyPluginTables()方法。
分析到此结束,我的分析可能不全面,也可能有错误,请大家批评指正哈。