Hibernate associations with an interface - java

I'm hoping someone can help me figure out a problem I am having with hibernate.
I am working on a billing system where different types of entities can be invoiced. The entities implement an "Invoicable" interface.
In my invoice class I have this line
#ManyToOne(fetch = FetchType.EAGER)
private Invoiceable responsibleEntity;
The invoiceable interface looks like this
#MappedSuperclass
public interface Invoiceable
{
// Name to display as entity responsible
String getInvoiceOwnerName();
// Get email address to send invoice
String getInvoiceOwnerEmail();
}
I'm getting an exception when I run this
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on models.Invoice.responsibleEntity references an unknown entity: interfaces.Invoiceable
I've tried googling it and reading some similar posts but I can't get anything to work. Does hibernate support this type of mapping?
Thanks

You have to use Inheritance in the Hibernate way to do this. Details can be found in the --> Hibernate Inheritance Doc
Additional information:
Hibernate is not able to wire types together where no database table is behind it. What does this mean for you. MappedSuperclasses do not have a table so there's nothing to wire together. So this is out of business. Most important keep in mind. When you request to read all parent objects. To which tables should he join? This is the reason why the inheritance system of hibernate comes in to play. You have to change the interface to a normal class. This should not be to much of a problem. Now choose an inheritance Strategy of your choice. Each of them have their pros and cons. Please read the doc to get an idea of which is best for your situation.
The following is an example of a the single table approach with an Invoice class.
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(
name="invoiceType",
discriminatorType=DiscriminatorType.STRING
)
#DiscriminatorValue("Invoice")
public class Invoiceable { ... }
#Entity
#DiscriminatorValue("CustomInvoice")
public class CustomInvoice extends Invoiceable { ... }

Related

How to manage empty entities and/or entities with no tables using discriminators/inheritance

I've asked a few times on other sites (and here) but I figure I would try again because I really haven't found an answer. I'm sorta new to hibernate, and I'm scared of posting in hibernate's forums. I'm using mainly JPA annotations with Hibernate 3.6.
I have the following schema:
So basically this is a legacy DB. Nomination is the central table, and I have 4 specific types of Nominations:
Coworker (which only uses NOMINATION table columns as attributes)
Team (NOMINATION + TEAM_NOM tables)
Idea (NOMINATION + IDEA_NOM tables)
Success (NOMINATION + SUCCESS_NOM tables)
So what I've done is use a discriminator (and inheritance) to establish their entities. For example:
Here's Entity Nomination:
#Entity(name = "Nomination")
#Table(name = "NOMINATION")
#DiscriminatorColumn(name="CATEGORY_CODE", discriminatorType = DiscriminatorType.STRING, length = 1)
#Inheritance(strategy=InheritanceType.JOINED)
public abstract class Nomination extends AuditableEntity {
And here's how I'm coding Team, Idea and Success Entities:
#Entity(name = "TeamNom")
#Table(name = "TEAM_NOM")
#DiscriminatorValue("T")
#PrimaryKeyJoinColumn(name = "NOM_ID")
public class TeamNom extends Nomination {
Now for Coworker I did the following:
#Entity(name = "CoworkerNom")
#DiscriminatorValue("C")
#PrimaryKeyJoinColumn(name = "NOM_ID")
public class CoworkerNom extends Nomination {
As you can see I have a big problem. Hibernate is looking for a table called "CoworkerNom", but I don't have any in our DB. I have tried putting in "Nomination" as table because I was out of ideas, but logically it gives me a circularity dependency error.
So how do I approach this entity which has no table and no attributes? The other Entities are working fine obviously.
In hibernate you are going to have to create a table with the attributes for each subclass of Nomination, so you are going to have in practice this table only populated with ID's... The rationale behind this I think is so that you have the advantage that if you want to extend this subclass with specific properties in the future, you can do so without having much your annotations or schema changing.

Can I remove the discriminator column in a Hibernate single table inheritance?

We use single table inheritance for every table in our application. This allows different instances of the same application stack to work with the same DAOs while their entities might differ slightly potentially containing information unique to that instance. An abstract class defines the basic table structure and an extension defines additional columns, if needed by that instance:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Table(name = "client")
public abstract class Client extends AbstractPersistable<Long> {
// ...
}
application A:
#Entity
public class ClientSimple extends Client {
private String name;
// getter, setter
}
application B:
#Entity
public class ClientAdvanced extends Client {
private String description;
// getter, setter
}
Now a DAO can work with Client objects for application A and B but application B can define additional information for its client object that may be read by a manager method unique to application B:
application A:
Client client = new ClientSimple();
clientDao.save(client);
application B:
Client client = new ClientAdvanced();
clientDao.save(client);
Unfortunately this means there is a DTYPE column in every table (or any other name that I might choose). Is there any way to get rid of this? We don't need it and it's using up DB space...
Thanks!
EDIT
Important to note: #MappedSuperclass won't work. We're using QueryDSL as our HQL abstraction layer. This requires automatically generated Query Type classes for type save querying. These however will only be generated correctly if the abstract class is annotated with #Entity.
This is neccessairy because we want to query against the abstract class Client while in truth querying ClientSimple in application A and ClientAdvanced in application B:
So in any application this will work:
query.where(QClient.client.name.equals("something");
and in application B this will work:
query.where(QClientSimple.client.description.equals("something else");
EDIT2 - boil down
It seems to boil down to this: Can I configure hibernate at deploy time to set the discriminator type for an inhertited entity to a fixed value. So going with my example a Client will always be ClientSimple in one application and ClientAdvanced in the other so that I don't have to store that information in the database?
Like I said: Each application will be an instance of the base application stack. Each application might define additional columns for their local database but ALL objects will be of the same type for that instance so we guarantee that the discriminator is always the same making it redundant in the database and a use case for hibernate configuration.
I know, this is a very old question, but I encountered this problem recently and this might prove useful to someone.
This can be done using Hibernate's #DiscriminatorFormula annotation. The following description is based on the book Java Persistence with Hibernate, section 5.1.3; the relevant part begins at page the last paragraph on page 202.
With #DiscriminatorFormula you can provide an SQL statement that determines the value of the discriminator while fetching the relevant rows from the database. In your case, it would have to be a simple string that evaluates to some arbitrarily selected value. For this to work, you need to decide upon a name that would be used for your Client entity. Suppose that you select 'GenericClient' as the name of the entity. This is the name that should appear within #Entity annotation as the value of the name attribute. So, the complete example, in your case would look like the following.
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Table(name = "client")
#DiscriminatorFormula("'GenericClient'") // *1*
public abstract class Client extends AbstractPersistable<Long> {
// ...
}
// Application A
#Entity
#DiscriminatorValue("GenericClient") // *2*
public class SimpleClient extends Client {
// ...
}
// Application B
#Entity
#DiscriminatorValue("GenericClient") // *3*
public class AdvancedClient extends Client {
// ...
}
The line that is denoted by '1' is a part of the SQL snippet that will always return 'GenericClient' as its value. The subclasses of the Client should always be annotated with the #DiscriminatorValue("GenericClient"). What this means is that when Hibernate fetches the rows from the DB, the type of the object to be constructed would always be the specific subclass of Client.
If the package where the subclasses of Client reside, and the name of the subclasses are fixed:
In that case, the #DiscriminatorValue("GenericClient") on the sub-classes wouldn't be required, all you would need to do is:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Table(name = "client")
#DiscriminatorFormula("'com.example.fixed.path.FixedSubClassName'")
public abstract class Client extends AbstractPersistable<Long> {
// ...
}
The subclasses wouldn't need any annotations. The discriminator-value defaults to the entity-name, which itself defaults to the fully-qualified class-name.
Note: The SQL statement inside #DiscriminatorFormula() can be any valid SQL statement for your targeted DB server.
If you never need to use both ClientSimple and ClientAdvanced in the same application you can declare Client as #MappedSuperclass rather than #Entity.
In Hibernate, Single Table per Class hierarchy would always need a discriminator column to distinguish between the entities as all classes in one hierarchy are stored in one table.
Here is an example of Hibernate Single Table per Class Hierarchy.
But you may want to consider a different Hierarchy scheme like below:
Hibernate Single Table per Subclass
Advantages
Using this hierarchy, does not require complex changes to the
database schema when a single parent class is modified.
It works well
with shallow hierarchy.
Disadvantages
As the hierarchy grows, it may result in poor performance.
The number of joins required to construct a subclass also grows.
Hibernate Single Table per Concrete class
Advantages
This is the easiest method of Inheritance mapping to implement.
Disadvantages
Data thats belongs to a parent class is scattered across a number of
subclass tables, which represents concrete classes.
This hierarchy is not recommended for most cases.
Changes to a parent class is reflected to large number of tables
A query couched in terms of parent class is likely to cause a large
number of select operations
I would suggest you to have a look at Single Table Per Subclass scheme. Although I am not sure about your exact requirement. But this may help.

How to implement a 3 Many-to-Many relationship with Hibernate?

I'm not 100% sure this is only a Hibernate issue as this might be a more abstract decision but I'll give it a try.
Since the problem description is a bit lengthy I'll first state that what I'd like to do is see if I can change the implementation to something which more resembles a Best practice implementation then this.
I have 3 entities, relevant to this issue: Workstation (ws), Employee and Organization-unit(org-unit).
An Employee can belong to one org-unit.
An Org-unit can hold many employees.
A Workstation is used to display data of an Org-unit(in general), Of an Org-unit and a specific employee in it and an employee which does not belong to an org-unit.
Currently, for various reasons which were out of my control, we do not use any associations between the entities in Hibernate or via DB-Constraints but we just use Columns which logically serve as Foreign-Keys.
We currently have an additional table which has 4 columns:Id,WSId,EmployeeId,OrgUnitId.
This allows a WS to refer to an orgunit (where employeeId is null),to an employee without an org-unit (orgunitId is null) or to an employee and org-unit (where none are null).
I'd like to be able to know:
1.Given a WS, which employees is it following and which org-units and how (i.e., alone, with an employee? which?)
2.Given an employee, which WS are monitoring it.
3.Given an org-unit, which WS are monitoring it and how (i.e., alone, with an employee? which?)
This issues relates to the Presentation layer as it dictates the view will be generated BUT it is a part of the domain model as a user, will use, an interface to manipulate these monitoring mappings and so these mappings are a part of the domain model.
I'm not sure if what I have is not the least evil among options, and I would greatly appreciate comments and suggestions.
EDIT From one of the answers I think it is not clear enough that a WS can display data for many such mappings at the same time, in a mixture of the above sorts (org-unit, employee etc.)
OK, I don't know how to implement this on the database side, but here is an Entity Model that should cover the relationship you are talking about.
Edit:
This is a new version in response to your comments. Now every WorkStation has n bindings each of which can have employee or orgunit or both (use DB constraints to ensure they don't have neither).
You can also access the bindings per orgunit and per employee, which should make the above queries much easier:
#Entity
public class OrgUnit{
#OneToMany(mappedBy="orgUnit")
private Set<Binding> bindings;
}
#Entity
public class Employee{
#OneToMany(mappedBy="employee")
private Set<Binding> bindings;
}
#Entity
public class Binding{
#ManyToOne(optional = true)
private Employee employee;
#ManyToOne(optional=true)
private OrgUnit orgUnit;
#ManyToOne(optional=false)
private WorkStation owner;
}
#Entity
public class WorkStation{
#OneToMany(mappedBy="owner")
private Set<Binding> bindings;
}
Sample Client code:
public Set<WorkStation> getWorkstationsPerEmployee(final Employee employee){
final Set<WorkStation> workStations = new HashSet<WorkStation>();
for(final Binding binding : employee.getBindings()){
WorkStation workStation = binding.getOwner();
if(workStation!=null)
workStations.add(workStation);
}
return workStations;
}
Sounds like all you really need is a nullable FK on Employee to OrgUnit, and two nullable FKs on WS to both Employee and OrgUnit. To see which WS are monitoring an employee, just get all the WS with matching emp_id columns. Same with the WS monitoring an OrgUnit, possibly with the additional stipulation of emp_id being null or not (depending on if you need to handle those situations separately). No idea where "patients" fits in, you didn't give any details about that.

Hibernate ManyToMany and superclass mapping problem

I need to create a relation in Hibernate, linking three tables: Survey, User and Group.
The Survey can be visible to a User or to a Group, and a Group is form of several Users.
My idea was to create a superclass for User and Group, and create a ManyToMany relationship between that superclass and Survey.
My problem is that Group, is not map to a table, but to a view, so I can't split the fields of Group among several tables -which would happen if I created a common superclass-.
I thought about creating a common interface, but mapping to them is not allowed.
I will probably end up going for a two relations solution (Survey-User and Survey-Group), but I don't like too much that approach.
I thought as well about creating a table that would look like:
Survey Id | ElementId | Type
ElementId would be the Group or UserId, and the type... the type of it.
Does anyone know how to achieve it using hibernate annotations? Any other ideas?
Thanks a lot
I posted a very similar answer yesterday. To summarize, you can't use a mapped superclass because a mapped superclass is not an entity and can't be part of an association (which is what you want) but you can use an abstract Entity with a TABLE_PER_CLASS inheritance strategy to obtain a similar result.
Something like this (not tested):
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractEntity {
#Id #GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
#ManyToMany(mappedBy="entities")
private Set<Survey> surveys = new HashSet<Survey>();
...
}
#Entity
public class User extends AbstractEntity {
...
}
#Entity
public class Group extends AbstractEntity {
...
}
#Entity
public class Survey {
#Id #GeneratedValue
private Long id;
#ManyToMany
private Set<AbstractEntity> entities = new HashSet<AbstractEntity>();
...
}
References
Annotations, inheritance and interfaces
using MappedSuperclass in relation one to many
Polymorphic association to a MappedSuperclass throws exception
You can use the table per concrete class inheritance strategy, hibernate will replicate all properties for each subclass, this will work with a view.
I would also suggest the composite pattern for users/groups (which is close to your first option).
http://en.wikipedia.org/wiki/Composite_pattern
This is possible. Such an 'inherited properties' approach can be achieved by defining the superclass as a MappedSuperclass.
EDIT:
There is also some alternatives listed in section 2.2.4 in the hibernate annotations reference doc, section 2.2.4.4 covers MappedSuperclass.

Hibernate Annotation for Entity existing in more than 1 catalog

I have a Person entity mapped by Hibernate to a database table in a database catalog "Active". After a period of time, records in this database table in the "Active" catalog are archived/moved to an exact copy of the table in a database Catalog "History". I have the need to retrieve from both the Active and History Catalogs. Is there a better way to model this with Hibernate annotations than making an abstract class that 2 classes extend from.
This is what I have now.
#MappedSuperclass
public abstract class Person {
#Id
private Integer id;
private String name;
}
#Entity
#Table(name="Person", catalog="Active")
public class PersonActive extends Person {
}
#Entity
#Table(name="Person", catalog="History")
public class PersonHistory extends Person {
}
To my knowledge, that would be the right way to do it with annotations (you kinda have two tables so you need two entities). Then run a polymorphic query on the Person entity. I find this pretty clean by the way.
PS: Can you add a pointer on how to do this with mapping files, I'm really curious.
My thought would be to write a query to select both tables from db A and B. then create a query with hibernate and map it to your class.
example:
#Entity
#NamedNativeQuery(
name="GetAllPerson",
query="select * from A.Person inner join B.Person on A.Person.Id = B.Person.Id"
)
public class Person {
...
}
Not sure if it could work, your question made me also curious about the best way to do it :). I'll test it tonight after work and see if its any good.
I think there is a subproject of hibernate named shards. It is designed to work with multiple relational databases. If you want to use it, you may need big changes in your code.

Categories