I've seen many examples and real-life projects where database table columns have a unique prefix that corresponds to the table name. Small example:
CREATE TABLE customers (cus_id BIGINT, cus_name VARCHAR(255), cus_adr_id BIGINT);
CREATE TABLE addresses (adr_id BIGINT, adr_postcode CHAR(5));
How can I accomplish this in Hibernate or JPA?
I already tried to implement PhysicalNamingStrategy but that doesn't seem to have access to the entity itself so I have no way to know the entity when setting the column name.
I now hope that there is a better way than placing annotations above every single variable declaration. That's pretty verbose and doesn't fit to my expectations to ORM which in my eyes should ideally provide an automatic way of mapping. Moreover, the ID and other properties that are shared among entities I have to keep in a base-class entity which makes the annotations even more complicated.
Related
We inherit a database and we need to do an API to communicate with it. We are considering the possibility to use JPA / Hibernate, but there is maybe a blocking constraint.
To facilitate maintenance, our predecessors have split a table into multiple with a business parameter.
So, there are some tables named ELEMENT_xxx where xxx is a specific name.
Is it possible to make a JPA entity with a constructor which take the specific name in parameter and then allow to query on the right table?
Thank you
PS:
If not, i think the solution could be to create an entity for each table. But we don't know how many tables they have, and we understood that they can create new.
I'm having difficult with dbUnit's org.dbunit.dataset.NoPrimaryKeyException. I've got a class, let's say A, that has a Set<B> property, where B is an enum. I use Hibernate's hbm2ddl tool to generate my database schema, and then use dbUnit to populate my database ready for DAO unit testing.
I'm trying to populate my database using dbUnit xml, but I'm getting a org.dbunit.dataset.NoPrimaryKeyException when dbUnit tries to delete the entries I've defined for the table A_B (that has been auto generated by Hibernate)
I've had a look at the solution proposed on the following question:
Using DbUnit with tables which do not have primary keys, but this requires that I either:
Define an id for each and every class as a primary key (I already have primary keys defined that are not necessarily numeric); or
Specify exactly which primary keys are used for which classes in the accept method.
Is there any way that I can specify the default primary key should be used, unless there isn't one, in which case we should use all columns in the table?
(As an aside, I persist the enum using Hibernate and JPA annotations using a similar method to that described at http://appfuse.org/display/APF/Java+5+Enums+Persistence+with+Hibernate)
I am thinking about switching from a self-implemented versioning-solution to Hibernate Envers, but I am not quite sure yet. I have read a lot about it, but I am concerned about schema changes and how Envers deals with them after having historized data according to an older schema.
What is your experience with Envers in this regard? How do you deal with schema changes and existing data with Envers?
Update 1:
It is not just about adding removing simple columns from a table, but e.g. when changing a simple Forein-Key-Relationship into a separate entity with two 1:n-relationships (M2M with attributed columns. This is a "logical" change in your data model. How do you deal with that when using Envers, when there is already historized data according to the old model? Is there an alternative to manually write sql-scripts and transfering them into the new representation?
In my experience, Envers simply copies every field from your entity table to its audit tables. The copied fields in the audit tables have no constraints on them, including nullability and foreign key constraints, so there's no problem with adding or removing such constraints on the real tables. Any kind of relationships you add to your entities will just be new audit columns and/or tables added under Envers, and it's up to you to correctly interpret them in their historical context.
For your example, if I understand correctly, of switching from a join-column-based relationship to a join-table-based one, you'd simply have the old join column coexisting with the join table, and at the point of the cutover, the former will cease being populated in favor of the latter. Your history will be completely preserved, including the fact that you made this switch. If you want all the old data to fit into the new model in the audit tables, it's up to you to do the migration.
There shouldn't be problems with modifying the existing schema as Envers relies on your #Entities to create the audit tables. So if you add or remove a column from an existing table, as long as this change is reflected in your #Entity / #Audited JavaBean, it should be ok.
The foreign key refactoring should be fine with Envers. As Envers creates a join table even for one-to-many relationship, it should be straight to change it to become many-to-many relationship. I extracted one paragraph from official document:
9.3. #OneToMany+#JoinColumn
When a collection is mapped using these two annotations, Hibernate
doesn't generate a join table. Envers, however, has to do this, so
that when you read the revisions in which the related entity has
changed, you don't get false results.
To be able to name the additional join table, there is a special
annotation: #AuditJoinTable, which has similar semantics to JPA's
#JoinTable.
One special case are relations mapped with #OneToMany+#JoinColumn on
the one side, and #ManyToOne+#JoinColumn(insertable=false,
updatable=false) on the many side. Such relations are in fact
bidirectional, but the owning side is the collection (see alse here).
To properly audit such relations with Envers, you can use the
#AuditMappedBy annotation. It enables you to specify the reverse
property (using the mappedBy element). In case of indexed collections,
the index column must also be mapped in the referenced entity (using
#Column(insertable=false, updatable=false), and specified using
positionMappedBy. This annotation will affect only the way Envers
works. Please note that the annotation is experimental and may change
in the future.
I am working on converting a legacy system to use hibernate (version 3.3.x) instead of using hand crafted SQL. I have run in to some problems mapping my datamodel that pertians to composite keys. I've created a solution I think works, but I am not overly fond of it. Hence, I would like to see how the diagram below could/should be mapped and see if I am on the "right" track.
In the diagram StuffTypes is a pretty static table that don't change (no inserts or updates). Parent is the only table that currently has a DAO class associated to it (the others should be persisted when the parent instance is). Stuff has a StuffType and a number of SubStuff associated with it. Finally, SubStuff is just a many to many mapping table between Stuff and StuffTypes.
What is the best way of mapping these entities to Java objects using annotations?
Personally, I often refer to the section 3.2 Primary Keys through -ToOne Relationships of the JPA Wiki Book. And read also 3.1 Composite Primary Keys.
Adding a primary key stuff_id to the Stuff table and another primary key substuff_id to SubStuff is less complicated. Composite keys are possible, of course. If seen solutions where #Embeddable classes have been introduced to model the composite keys.
Hibernate Reference is your best bet. Try this, Mapping Entities with Composite Keys.
I've been dealing with composite id's and asked a few questions and I was recommended to replace my composite PK's with a single id column, and to control integrity with indexes... All of this related to the fact that mapping composite id's isn't that simple...
On the other side, some people encourage the usage of composite id's that are accord to the domain model...
So I decided to ask: When will you encourage using composite PK's in your DB while using Hibernate?
I personally favor composite ids because they emerge out of the entity-relationships. However, Hibernate suggests the use of simple integer ids. But I think you don't have to choose one over the other.
You can have your composite id constituent fields to become a <natural-id>
And have a private integral field in the class for hibernate to use as the id.
See http://docs.jboss.org/hibernate/stable/core/reference/en/html/mapping.html#mapping-declaration-naturalid