Play!框架 - Evolutions数据库问题

11

我正在使用Play!框架2.0,遇到了一个涉及数据库的恼人问题。

假设我有一个User(扩展Model)类,该类具有几个属性(first_namelast_nameemailpassword等)。

在某些时候,我想添加一个新属性,比如last_ip(它真的没有什么关系)。因此,我将属性添加到User类中,然后编译并运行。

问题是:我收到了有关数据库更改的红色警告(显然),询问我是否要按"APPLY CHANGES"(如果我记得正确的话)。这很好,但是! 所有数据库记录都被删除了

总之:我想添加一个新字段,但我不想失去已经添加到数据库中的所有记录。这可行吗?


您的帖子中有几个迹象表明您可能正在做出一些危险/有问题的设计选择。根据列名,您似乎高度可能存储明文密码,而不是加盐哈希密码。这样做非常糟糕,特别是如果您没有加密密码,而是以明文形式存储它。请不要存储用户密码,使用身份验证服务和安全的身份验证协议。 - Craig Ringer
考虑使用JSSEJava GSSJava SASL来处理身份验证,不要在应用程序中存储密码 - 或者更好的是,使用OAuth或OpenID,这样其他人可以为您管理密码。您不想成为下一个被破解的网站,告诉所有用户它正在存储明文未加盐的密码;嘲笑是刺痛人心的。 - Craig Ringer
此外,您需要阅读《程序员关于姓名的错误观念》和《Stilgherrian的“只有一个名字”》。 - Craig Ringer
4个回答

18

首先,您需要通过删除conf/evolutions/default/1.sql文件中的前两行注释来禁用Evolution文件的自动生成:

# --- Created by Ebean DDL
# To stop Ebean DDL generation, remove this comment and start using Evolutions

# --- !Ups
...

接下来,您需要创建第二个文件,名为conf/evolutions/default/2.sql,其中包含对数据库模式的更新,以及 Ups 和 Downs 部分:

# --- !Ups
ALTER TABLE USER ADD COLUMN last_ip varchar(30) DEFAULT NULL;

# --- !Downs

ALTER TABLE USER DELETE COLUMN last_ip;

你能否将你的回答切换到社区维基上? :) 问题一直存在,所以我们可以根据你的答案编写完整的指令。 - biesior

4
你可能正在执行破坏性的进化操作。如果你查看1.sql(或者你的进化文件名),在DOWNS下面有像“DROP DATABASE X”这样的语句。每当Play检测到进化文件中的更改时,它会运行所有的down进化,然后重新应用up进化,导致所有数据丢失。
更多信息请参见:http://www.playframework.org/documentation/2.0.2/Evolutions

2
好的,我大致上已经读懂了。但是当您向数据库添加新字段但又不想失去之前添加的所有记录时,应该采取什么正确的行动呢?当您处于生产阶段时,这个问题至关重要。 - socksocket
哦,对了,我的错。我认为你应该删除破坏性的降级操作,可能需要添加一个2.sql文件,在其中使用ALTER SQL语句向数据库中添加一个字段。 - Henry Henrinson
您可以禁用下降部分,因为在具有“play.evolutions.autoApplyDowns=false”配置的生产环境中可能存在危险。 - Haimei

3
我建议您查看Liquibase。Liquibase处理数据库变更,非常灵活且与数据库无关。我在我的应用程序中使用它来确保在应用数据库更改时不会删除任何内容。请参考Liquibase

我从未使用过Play,所以无法提供帮助。请访问Liquibase的网站获取更多信息,这是一个文档完备的项目。 - siebz0r

2

您可以通过在application.conf中设置evolutionplugin=disabled来禁用Evolutions。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接