views:

183

answers:

5

I am developing a Java Application that uses Hibernate and is connected to an Oracle instance. Another client is looking to use the same application, but requires it run on MS SQL Server. I would like to avoid making changes to the existing annotations and instead create a package of xml files that we can drop in depending on the environment.

One way to do this is using JPA XML configuration to override the existing class annotations. However, JPA does not support generic generators, which is a requirement due to the structure of our legacy database. The other way that I am looking into is to use Hibernate XML configs to remap entire classes and have access to the generator xml tag. This solution has some issues though:

  • Hibernate does not allow you to selectively override entity members
  • Hibernate does not allow you to re-map the same class (e.g. org.hibernate.AnnotationException: Use of the same entity name twice)

Does anyone have any experience with overriding annotations using Hibernate XML Configuration files or is JPA the only way to go?

Update with an Example

In Oracle, Sequences are used to generate unique IDs when inserting new records into the database. An id would then be annotated in the following manner:

@Id
@GeneratedValue(generator="EXAMPLE_ID_GEN", strategy=GenerationType.SEQUENCE)
@SequenceGenerator(name="EXAMPLE_ID_GEN", sequenceName="SEQ_EXAMPLE_ID")
@Column(name = "EXAMPLE_ID")
public String getExampleId() {
    return this.exampleId;
}

However, MS SQL Server does not have the concept of Sequences (Ideological differences). Therefore, you could use a table generator to simulate sequences.

@Id
@GeneratedValue(generator="EXAMPLE_ID_GEN", strategy=GenerationType.TABLE)
@TableGenerator(name="EXAMPLE_ID_GEN", tableName="SEQUENCE", valueColumnName="VALUE", pkColumnName="SEQUENCE", pkColumnValue="EXAMPLE_ID")
public String getExampleId() {
    return this.exampleId;
}

Two different configurations for two different types of databases. Keep in mind that this is a legacy database and that we aren't going to rewrite our application to support SQL Server identities, the native id generator for SQL Server (which would also require a different annotation).

To alleviate this, I have looked into using Hibernate's @GenericGenerator and point it to a class of my own creation that models org.hibernate.id.SequenceGenerator (or something similar) and also customize the structure of the table by extending org.hibernate.id.TableStructure.

Back to my original question - is any of this possible with an XML override?

A: 

I would say that if your annotations are database specific, you're doing it wrong.

james
In the real world, where the terms 'legacy', and 'existing application' are used, saying "you're doing it wrong" isn't helpful. Trying to bridge the gap between Oracle and SQL Server, who have idealogical differences on database design, is going to require differences in configuration (i.e. annotations)
rynmrtn
@rynmrtn: I think what he's trying to point out is that JPA should already be database independent... the datastore is already configurable via persistence.xml.
R. Bemrose
His answer specifically referenced database-specific annotations, not persistence.xml. It's still a non-answer.
rynmrtn
I stand by this answer in general for ORM's. that said, i'll try to give some targeted advice in another answer.
james
A: 

I think that if you don't use AnnotationConfiguration when configuring your SessionFactory, the annotations will be omitted.

So, use Configuration.

Bozho
A: 

For your generator problem (for which the solution would normally be "use the native generator" but doesn't work for you due to working with a legacy db), you could probably extend the SQLServerDialect and override the getNativeIdentifierGeneratorClass to return a (possibly custom) generator that does what you need for your legacy db.

james
A: 

I have come across the need to mix-n-match legacy with new schemas/databases before in a Grails (GORM) application, which of course is running Hibernate 3 underneath.

Would not say "you're doing it wrong" - but I would keep the JPA @Annotations to the very basics like @Entity and @Column and leave it to the Hibernate dialect, which is also specified in the XML configuration file.

You might experiment with subclassing the Oracle10gDialect with one that assigns a sequence generator to all tables, versus a Sybase one which does not.

Please see this post on how to implement this.

UPDATE: What james and I are suggesting (almost in the same minute) is to setup multiple persistence-unit sections of your persistence.xml file.

This allows one to use @Entity and @Id without supplying details in the class. The details come in the hibernate.dialect property. I suggested subclassing Oracle10gDialect (and james the SQLServerDialect) - those would do the choosing as to the table naming, id generator strategy, etc.

See --> https://forum.hibernate.org/viewtopic.php?f=1&t=993012

mikesalera
If you're saying to keep the JPA annotations to the basics, how would you specify the way the IDs get generated?
rynmrtn
What james and I are suggesting (almost in the same minute) is to setup multiple persistence-unit sections of your persistence.xml . This allows you to use @Entity and @Id without supplying details in the class.
mikesalera
+1  A: 

If you rewrite the annotations in HBM XML files, you could maintain two sets of such XML and pick which ones to use via Hibernate's mapping directives. I've done this in Hibernate Core, but not in a J2EE/JPA environment so I don't know if there are any gotchas in that respect.

The biggest downside is it likely will be a lot of work to remove all your annotations and rebuild them in XML.

divestoclimb