views:

345

answers:

1

In my hibernate application there is annotation driven object: AuditEvent. Its very simple and has no foreign key relationships. I archive old entries in this table by moving them to another table OldAuditEvent, which is a clone of the AuditEvent table.

Right now we generate the DDL for the entire application using hbm2ddl (on our annotated datamodel) and manually copy/paste the AuditEvent table and change its name to create OldAuditEvent.

I want to automate the build process, is there any way to tell hbb2ddl: "hey take this entity, change the table name to X and regenerate it's DDL"?

Update: I was able to get this working by the approach you outlined. The only trouble was getting at the AnnotationSessionFactoryBean since it is a factory bean and spring will only give you the output of its factory. I created ConfigExposingAnnotationSessionFactoryBean (extending AnnotationSessionFactoryBean) to expose the bean factory through a static -- sort of a hack but all I want to do is run a build time task.

Configuration cfg = ConfigExposingAnnotationSessionFactoryBean.s_instance.getConfiguration();

PersistentClass pClass = cfg.getClassMapping("com.myco.LoginAttempt");
pClass.getTable().setName("ArchiveLoginAttempt");

Dialect dialect = Dialect.getDialect(ConfigExposingAnnotationSessionFactoryBean.s_instance.getHibernateProperties());

// only output create tables, not indexes or FK
for (String s : cfg.generateSchemaCreationScript( dialect )) {
 if (s.contains("create table") && s.contains("Archive")) {
  m_outstream.print(s);
  m_outstream.println(";");
 }
}
+2  A: 

It's doable but rather messy and, most likely, not worth it in this case.

You'll need to dynamically alter Hibernate's Configuration object before SessionFactory is built. I you're using Spring, this can be done by overriding postProcessAnnotationConfiguration() method of AnnotationSessionFactoryBean; otherwise you'll just need to do it using your Configuration object prior to invoking buildSessionFactory() on it.

You can get access to class / table mappings via configuration.getMappings(). You will then need to find your table mapping via getTable(), create a copy with new name via addTable() and replicate all columns / keys via Table API.

You can then generate the DDL script via generateSchemaCreationScript() or generateSchemaUpdateScript() methods of Configuration object.

As I said, probably not worth it in this case :-)

ChssPly76
I will try this and see if it works! Even for 2 tables, I think it is worth it -- manual steps in a cross-platform build process just drag things down and cause unexpected problems.
Justin
Good luck with your implementation. The above approach works for me, though I'm using it for a different purpose (runtime entity mapping manipulation). I've got to say, though, that I'm quite annoyed by Hibernate reordering columns in DDL script - I want to maintain the same order as in source code annotations. Have you somehow resolved that or is that not an issue for you?
ChssPly76
Our dev process is: annotated POJO -> DDL. We always go through hibernate property names, so we don't care about column positions. If hibernate is reordering randomly, that means its probably using a HashSet/Map somewhere internally. Find the code switch it to a TreeSet/Map and you might get consistent ordering?
Justin
* that would give you sorted and consistent order, but not what you want. You need to apply a sort at the end process which scans the annotations and reorders the internal hibernate structure based on the class annotation.
Justin
Yes, I do that for regular attributes, and it's a huge pain :-) It's next to impossible to do that for associations, though (without rewriting a significant part of Hibernate metadata objects) so they always go last in the table. I've made my peace with that :-) but when I saw you were generating DDL from POJO annotations I figured I'd check if you have faced and perhaps resolved that issue.
ChssPly76