Hibernate: #UniqueConstraint Across Multiple Tables? - java

I have a data model in which a number of entities inherit some common attributes from a single superclass entity. I am using InheritanceType.JOINED on the superclass, which causes Hibernate to create a single table for attributes defined in the superclass, with subclass tables containing only columns that are added by the subclass (so to load the attributes for a subclass instance, a join is performed between the two tables). That is all working fine.
What I'd like to do, however, is specify a unique constraint that includes fields in both the subclass and superclass tables. For instance, say that my superclass entity is something like:
Thing: {id, name}
...and then I have some subclass entities like:
Company: {address} //inherits 'id' and 'name' from 'Thing'
Employee: {company} //inherits 'id' and 'name' from 'Thing'
...and I want to configure Hibernate to automatically enforce that a given Company cannot have two Employee's with the same name. The company field is in the Employee table, but the name field is in the Thing table, so is there any way to get Hibernate to enforce this constraint, or do I need to do it programmatically whenever I add a new Employee?

If it's not possible in the Database it won't be possible with Hibernate. You can't create one constraint on multiple tables with SQL so neither in Hibernate.
You could work around this by creating a new Entity holding only the company and employee id and setting a unique constraint on those 2 fields but I would recommend enforcing this programmatically.

You could not use InheritanceType.JOINED, then everything ends up in a huge table, and you could write your constraint. As said before: What you want is just not possible in a relational DB.

Related

Hibernate, one to many from different table to general table

Good day.
Exists three tables(test):
User (id, user_name)
Object(id, object_name)
Property(id, property_value)
User, Object contain Property, so I'd like to use a special table EntityProperties(entity_id, entity_type, property_id), where entity_id - id from User or Object, and entity_type - user or object (params for tables User, Object).
May I implement it using Hibernate 4? If yes, please suggest with annotations and how better to do it.
Thanks,
Oleg
You can create a mapped super class EntityPropertyMap which has a property object and have concrete implementations(UserPropertyMap and ObjectPropertyMap) with table per class hierarchy strategy. Examples can be found http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/inheritance.html and http://viralpatel.net/blogs/hibernate-inheritence-table-per-hierarchy-mapping/
if User is also an Object then it can be done by making User extends Object and then the problem becomes mapping inheritance which you can read more about here
If this is a one way relationship from a User to Property and from Object to property then I think it can be achieved by normal mapping (one to many) and then there is no need for the entity_type column since you'll only be querying the Property table with an entity_id in hand. This way a User object will have a field Set<Property> properties; and the same for the Object class.

Mapping class to a table without a table name

I have many tables in my DB with exactly the same structure: same columns names and types.
The only difference between these tables is the their names (which I can only know in runtime).
I would like to create a mapping of a class to a table but giving the name of the table only during runtime (no static #Table annotation).
Is it possible?
Is there any other way to achieve my goal?
Directly - no. Because this is not a regular use-case. Normally you should not have dynamcally-generated tables. It is a valid use when you move some records to an archive table (or tables), but otherwise avoid it.
Anyway, you can make that work: make a native query, and map the result to your non-entity object. You will be able to select from any table and transform the result to an object. However, you can't insert or update that way.
Don't think associating or changing the table mapped to an entity dynamically is possible.
You can check #MappedSuperClass, which will allow you to define all fields in a class once and inherit them, so that there is no repetition and entities are empty class with mappings.
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e1168
If you know the table name dynamically you can always instantiate the mapped class accordingly.

JPA to retrieve name-value from child table without using model for child

This is something I'd really like to be able to do - resolve names based on id values without fetching the whole child model.
Here is an example of what I have, a Table say Employee and a Name_Details table
The Employee may look like this
Create Table Employee {
emp_idinteger not null generated by default as identity; -- generated pk
Department varchar(44);
emp_name_id Integer; -- fk to Name_Details table
...other details such as hire_date etc..
}
now emp_id is a foreign key to the name_details table which may look like this:-
Create Table Name_Details {
id Integer;
Name varchar(32);
Address Varchar(127);
Postcode Varchar(10);
--other details..
}
My question is that I'd like to model the first table Employee with a Java class but I am not interested in setting up a one-to-one relationship between the Employee class and the Name_Details table to fetch that whole Name_details table (as its quite large) the only information I want from this second class is just the Name field (found by joining the emp_name_id column with the Name_Details.id column.
So is it possible in JPA to say declare something like a transient variable in my Employee class called say String employeeName and have this retrieved by JPA based on the above relationShip?
This is a simplified example of what I have wgere there are several tables with name-value pairs and the master table has the values. I need this for reading and not updating/deleting etc.
I am not using JPA v1.x with EJB3 (and not hibernate) on WPS 6.1
Thx G
There are a few options.
The first is to just create a Name class that maps to Name_Details but only maps the name and id fields. Employee would then have a OneToOne to Name, and only the name would be read.
A second option is define Name_Details as a #SecondaryTable in Employee and map only the name from it. The JPA spec restricts the secondary table join to have to share the same id, but depending on what JPA provider you are using, using the 1-1 foreign key may be possible (EclipseLink does support this). You could also define a view the does the join and map to the view.
A third solution is to still map all of the Name_Details fields but define them as LAZY. If your JPA provider supports LAZY basics (or fetch groups), then these will not be fetch unless accessed.

Getting fewer columns with hibernate

I have a table with 11 columns, but I need to get only 2 of them in my application, I'm using spring/hibernate/DAO combination. For now I have a domain class which includes all 11 fields, and mapping file which maps all 11 columns in table. How do I use get just 2 of them not all?
Either:
Use projections - Pro: nothing to add - Con: Not typesafe (the result is a List of rows where each row is anObject[]):
select f.foo, f.bar from FatEntity f
Use a constructor expression in the SELECT clause (the specified class is not required to be an entity or to be mapped to the database) - Pro: typesafe solution - Con: More classes, unless you reuse FatEntity as holder in which case many fields will be null:
select new com.acme.FatEntityDetails(f.id, f.foo, f.bar) from FatEntity f
Note that if an entity class name is specified in the SELECT NEW clause, the resulting entity instances are in the new state (no persistent identity).
Use another entity mapped on the same table with only the required fields - Pro: It's a real entity that you can modify and update - Con: More classes.
from LightEntity
The main differences between #2 and #3 are:
2 doesn't require the holder to be an entity at all.
the holder in #2 could be an entity mapped on another table.
if #2 returns entities, they are in a new state (this might be a problem, or not).
Try:
SELECT myEntity.one, myEntity.two FROM MyEntity myEntity
You can even do :
SELECT new MyEntityDescription(myEntity.one, myEntity.two) FROM MyEntity myEntity
to get a list of entity descriptions.
If you never need more than those 2 columns of the table, you could change your hibernate mapping to map only those 2 needed columns to the entity class. Only map those table columns you want to access in your application. Keep in mind, that database constraints on the "ignored" columns can be violated like not null constraints, foreign keys or unique constraints.

hibernate: create table with names in lowercase

Hibernate: I want to have hibernate automatically generate my tables with names in lowercase.
For example, if my class is called com.myapp.domain.Customer, hibernate will generate a table named Customer. I want it to be called customer. I know I can use the #Table annotation to specify the table name per class. But I want it to happen "automagically".
Isn'it it the job for NamingStrategy?
You would get the name of the entity managed (i.e. Customer) and should decide the table name used (entityName.toLowerCase() in your case).
One thing I am not sure is if the NamingStrategies are taken into account when generating tables (hbm2ddl).

Categories