views:

215

answers:

4

Is it possible to change the target table for a Hibernate mapping? My use case is that while I get the data from one table, in cases where the data cannot be processed it is stored in a error table for later analysis.

Although it is possible to define entity-names in hibernate mappings, in my opinion it is not appropriate because it requires duplication of mappings. The same mapping would then exist for getting the data and a copy of it with a different entity-name for the error table.

Do you have any ideas how to approach and solve this problem?

+4  A: 

Short answer - no. Defining a separate mapping (via entity name) is the way to go.

Long answer - it's possible via runtime manipulation of Configuration prior to SessionFactory being built. You can get the mapping for the entity in question from Mappings as defined in Configuration, copy it under new entity name and associate it with a copy of the underlying Table under the new name. You would in effect still be defining a separate mapping, but doing it the hard way.

Take a look at this question.

ChssPly76
I've added a link to another (somewhat similar) question that has some details. In addition to what's described there, you'll also need to make a copy of your class (obtained from `Mappings.getClass()`) and add it back via `Mappings.addClass()` after changing entity name via `PersistentClass.setEntityName()`
ChssPly76
Thanks a lot, I'll try it this way. Don't you think that when you get the class (getClass()), you modify an internal instance, so this approach wouldn't produce another class, but only change it's entity name? A clone() would then become necessary.
lewap
That's why I said "make a copy" :-) It has to be a deep copy, too, clone() won't work (PersistentClass is not Cloneable anyway).
ChssPly76
BTW, if this is the only thing you need to do (e.g. copy mapping with different entity name; no other manipulations), do consider skaffman's suggestion. Applying XSLT should definitely be easier than Hibernate API manipulation.
ChssPly76
lewap
I've never said I'm copying the mappings :-) - I'm actually altering both mappings and database structure to support custom user-defined entities / properties. The code is quite involved; I can't copy/paste it in its entirety for legal reasons (plus it's really solving a different issue). But you're really looking at calling a bunch of set/get methods on Table and PersistentClass (https://www.hibernate.org/hib_docs/v3/api/org/hibernate/mapping/PersistentClass.html) or, rather, one of its descendants (RootClass unless you're dealing with inheritance)
ChssPly76
+2  A: 

As @ChssPly76 mentioned, you can jump through Hibernate's API hoops to get the raw configuration, fiddle them, and build yourself a new SessionFactory.

Another equally unpleasant solution would be to use XSLT to take your mapping config file and swap out the table name for something else, then feed that modified file into hibernate to build a new SessionFactory.

It's quite distatseful, but it does mean you can avoid getting mired in the depths of Hibernate.

skaffman
Sure, do you have an idea on how to do this programmatically?
lewap
You need to familiarise yourself with javax.xml.transform, as well as XSLT itself.
skaffman
I mean by using the Hibernate API
lewap
+1. Now there's thinking outside the box :-) This should definitely be easier though I'd probably run it during the build (or during app initialization but prior to SessionFactory being initialized).
ChssPly76
A: 

Hi,

As said,

Where the data cannot be processed it is stored in a error table for later analysis

Besides ChssPly76's answer, you can define a global HibernateException handler (if you use Spring to wrapper hibernate connections, you should use DataAccessException) and log errors details in your database or other devices such as a web page where you can see it in any place.

regards,

Arthur Ronald F D Garcia
A: 

Is it possible for you to use a superclass? If the data has all of the same mapping information, but belongs to a different table, then you could place the mappings on a common parent class of both entities. Use a mapped superclass to define the common properties, then define each concrete class as a different entity, inherity the properties. In hibernate annotations, this is accomplished using the @MappedSuperclass annotation on the parent.

RMorrisey