views:

50

answers:

3

I'm using Hibernate as the ORM for my application. I would like to know if there is a good solution to dealing with schema upgrades in my application when these upgrades are done by someone else. For example, I have a set of hbm.xml files and corresponding java classes generated using Hibernate tools. Now in production, everything works fine until the db schema is upgraded (tables/columns may be dropped/added). I do not (my app doesn't) have access to do that so how do I deal with this using Hibernate?

Thanks!

A: 

I've always preferred the other way around - make changes to classes only and set hibernate.hbm2ddl.auto to update. This way the database will be updated based on your classes. That makes much sense, because your objects are the center of your application, not their database representation.

Bozho
+3  A: 

I would like to know if there is a good solution to dealing with schema upgrades in my application when these upgrades are done by someone else.

There is no magical solution, you need to keep your mappings in sync with the schema. So you have two options:

  1. drop and recreate your mappings / classes from the schema ~or~
  2. update your mappings / classes manually to reflect the changes.

I would go for the second option, it is less intrusive and gives you more control (no big bang, you can keep old getter/setters, you can deprecate things).

In both case, communication is the key, you need to work with the people making the changes (and vice versa).

Pascal Thivent
A: 

Here is how i solve your problem

I work with a legacy system (Oracle) where other systems depends on it. In order to use it, DBA (not me) creates a database link with read-only access privilege. So if i need to create a new Entity for a new System without damaging (and worrying about) the database which is built on top of our legacy system, i do as follows

Suppose here goes our legacy class

@Entity
public class LegacySystemClass {

    private Integer id;

    /**
     * I have read-only access privilege
     * So insertable=false, updatable=false
     */
    @Id
    @Column(name="LEGACY_SYSTEM_ID", insertable=false, updatable=false)
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

}

And i need to create a class for the new System which depends on LegacyClass

@Entity
public class NewSystemClass {

    private Integer id;
    private LegacySystemClass legacySystemClass;

    @Id
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne
    @JoinColumn(name="LEGACY_SYSTEM_ID")
    public LegacySystemClass getLegacySystemClass() {
        return legacySystemClass;
    }

    public void setLegacySystemClass(LegacySystemClass legacySystemClass) {
        this.legacySystemClass = legacySystemClass;
    }

}

Now, i generate a SQL file according to

AnnotationConfiguration configuration = new AnnotationConfiguration();

configuration
    .addAnnotatedClass(NewSystemClass.class)
    .addAnnotatedClass(LegacyClass.class)
    .setProperty(Environment.DIALECT, <TYPE_YOUR_DIALECT>)
    .setProperty(Environment.DRIVER, <TYPE_YOUR_DRIVER>);

SchemaExport schema = new SchemaExport(configuration);
schema.setOutputFile("schema.sql");

/*
schema.create(<DO_YOU_WANT_TO_PRINT_TO_THE_CONSOLE>, <DO_YOU_WANT_TO_EXPORT_THE_SCRIPT_TO_THE_DATABASE>);
*/

/**
  * Make sure set up second parameter as false
  * See above
  */
schema.create(true, false);

It will generate a file called schema.sql which contains

create table LegacySystemClass (LEGACY_SYSTEM_ID integer not null, primary key (LEGACY_SYSTEM_ID))

create table NewSystemClass (id integer not null, LEGACY_SYSTEM_ID integer, primary key (id))

alter table NewSystemClass add index FK8533D2E95B9B5D88 (LEGACY_SYSTEM_ID), add constraint FK8533D2E95B9B5D88 foreign key (LEGACY_SYSTEM_ID) references LegacySystemClass 

I extract any SQL related to our legacy system such as LegacyClass. Our final schema.sql is shown as follows

create table NewSystemClass (id integer not null, LEGACY_SYSTEM_ID integer, primary key (id))

alter table NewSystemClass add index FK8533D2E95B9B5D88 (LEGACY_SYSTEM_ID), add constraint FK8533D2E95B9B5D88 foreign key (LEGACY_SYSTEM_ID) references LegacySystemClass (LEGACY_SYSTEM_ID)

I go to DBA room and ask to him

Can you run this schema.sql file to me, please ???

But as said by @Pascal Thivent

Communication is the key (Principle of Extreme Programming - XP)

Arthur Ronald F D Garcia