11

I'm using Play! framework 2.0 and I'm stuck on an annoying issue involving the database.

Suppose I have a User (extends Model) class which has few attributes (first_name, last_name, email, password etc).

At some point I want to add a new attribute, lets say last_ip (it doesn't really matter what it is). So, I add the attribute to the User class, compile and run.

The thing is: I get this red alert about database changes (obviously) which asks me to press "APPLY CHANGES" (if I remember correctly). That's fine BUT! all the database records are erased!

In conclusion: I want to a new field but I don't want to lose all the records I already added to the database. Is this possible?

DataNucleus
  • 15,497
  • 3
  • 32
  • 37
socksocket
  • 4,271
  • 11
  • 45
  • 70
  • There are several signs in your post that you might be making some dangerous/problematic design choices. Based on column name it seems highly likely that you're storing plaintext passwords, not [salted password hashes](http://crackstation.net/hashing-security.htm). That's all kinds of bad, especially if you aren't encrypting the password and are instead storing it in plain text. Please - just don't store user passwords, use an authentication service and a secure authentication protocol – Craig Ringer Aug 25 '12 at 15:48
  • Consider using [JSSE](http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html), [Java GSS](http://www.ietf.org/rfc/rfc2853.txt), or [Java SASL](http://docs.oracle.com/javase/1.5.0/docs/guide/security/sasl/sasl-refguide.html) to handle authentication and don't store passwords in your app - or even better, use OAuth or OpenID so someone else can look after the passwords for you. You don't want to be the next cracked site that has to tell all its users it was storing plain-text unsalted passwords; ridicule stings. – Craig Ringer Aug 25 '12 at 15:51
  • Also, you need to read [Falsehoods programmers believe about names](http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/) and [Stilgherrian's "only one name"](http://stilgherrian.com/category/only-one-name/) – Craig Ringer Aug 25 '12 at 16:04

4 Answers4

18

First you need to disable automatic generation of Evolution files by deleting the first 2 commented lines of the conf/evolutions/default/1.sql:

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

# --- !Ups
...

Then, you need to create a second file, called conf/evolutions/default/2.sql containing your update on the database schema with an Ups and a Downs section:

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

# --- !Downs

ALTER TABLE USER DELETE COLUMN last_ip;
ndeverge
  • 21,378
  • 4
  • 56
  • 85
  • could you switch your answer to the community wiki? :) the question returns still and still, so we can just write whole instruction based on your answer. – biesior Aug 30 '12 at 10:49
4

What you are probably doing is applying destructive evolutions. If you look in 1.sql (or whatever your evolutions file is), under DOWNS you have statemtnts like "DROP DATABASE X". Whenever Play detects changes in the evolution file, it runs all the down evolutions, then reapplies the up evolutions, resulting in all your data being lost.

Here is more info: http://www.playframework.org/documentation/2.0.2/Evolutions

Henry Henrinson
  • 5,203
  • 7
  • 44
  • 76
  • 2
    ok, I read and understood more or less in first reading. but what is the right action to take when you add a new field to the database but don't want to lose all the record which added before. the question is crucial when you're in production phase. – socksocket Aug 25 '12 at 15:41
  • Oh, right, my bad. What I believe you should do is remove the destructive downs and maybe add a 2.sql where you use and ALTER sql statement to add a field to your database. – Henry Henrinson Aug 25 '12 at 20:27
  • You can disable down section because it may be danger to have downs in production - in the configurations with "play.evolutions.autoApplyDowns=false" – Haimei Jun 08 '16 at 15:29
3

I suggest you take a look at Liquibase. Liquibase handles database changes, is super flexible and is database independent. I use it in my applications to make sure when I apply a database change things don't get deleted or whatever.

siebz0r
  • 18,867
  • 14
  • 64
  • 107
  • I've never worked with Play, so I can't. Have a look at Liquibase's web site for more info, it's a well documented project. – siebz0r Aug 26 '12 at 10:35
2

You could disable Evolutions by setting evolutionplugin=disabled in application.conf

Hao Zheng
  • 119
  • 6