Mapping an Interface As A Primary Key Via Hibernate - java

I have a class with it's own #Embeddable id class, let's call it ICompanyId. There are 2+ classes that implement ICompanyId. Classes that implement ICompanyId are the embedded id's for classes that implement ICompany (which there are 2+ implementing classes).
So, what I would like to do is this:
#EmbeddedId
public ICompanyId getId() { /* blah blah */ }
How do I tell Hibernate which implementing class to use? With a #ManyToOne or #OneToMany, all I would have to do is to specify a value in the targetEntity, but #EmbeddedId offers no such options. Can anyone help?
Jason

Have you tried #Target(CompanyIdImpl.class) (see: #Target)?
Keep in mind that this is a Hibernate-specific solution.

Related

JPA - What Annotation to use for a base class

I am a relative newbie to JPA, and I've read books (Java Persistence with Hibernate, Pro JPA 2 - Mastering the Java Persistence API), done google searches, but I have not been able to come up with a solution to the following situation.
I have a base class called History, that has all the persistent information needed to store the class's data members to a database. However, the class has an abstract method that needs to be overridden in derived classes. The derived classes do not have any persistence information of their own. They exist solely for two reasons:
to uniquely implement the abstract method defined in the base
History class
to persist the data to it's own table
The code below should make this clear.
#??? What annotation should I use here?
public abstract class History
{
#Id #GeneratedValue
private int id; // primary key
#Lob #Column(columnDefinition="mediumtext", length=65535)
protected String string; // string containing history
public abstract String foo();
}
#Entity
#Table(name="derived_history_1")
public class Derived1 extends History
{
public String foo()
{
return "Hello";
}
}
#Entity
#Table(name="derived_history_2")
public class Derived2 extends History
{
public String foo()
{
return "World";
}
}
I didn't think that #Inheritance(strategy=InheritanceType.JOINED) made sense, because nothing is being inherited in the derived classes that needs to be made persistent.
I tried #MappedSuperclass, but then the CascadeType.PERSIST and CascadeType.MERGE did not work when the derived classes were data members of another class. For example,
#Entity
#Table(name="part")
public class Part
{
...
#OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, optional=false, fetch=FetchType.LAZY)
#JoinColumn(name="history_id") // foreign key into history_part table
protected Derived1 history;
}
So I couldn't find anything that worked and fit my situation.
I hope I'm explaining this well enough that people can understand.
Does anyone know how to do this that's not a complete and total hack :-)
Thanks for any help.
Following annotations should work:
#Entity
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
Inheritance type TABLE_PER_CLASS makes inheriting entities to create own table and you also need to tell that History is also an Entity even it does not have table of its own.

Hibernate associations with an interface

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 { ... }

JPA/Hibernate inheritance without id

Is it possible to make inheritance in JPA/Hibernate without id?
My use case:
I have multiple entities and I want every time change is being done, timestamp being recorded. So I created AbstractResource and want each derived class inherit properties and logic (to avoid writing same stuff over and over again in each class).
My problem that hibernate wants an ID to entity, and I do not care about id, since my only concern is additional properties. And each entity can have whatever id it wants (String, int, long, different name, etc.).
I tried with Embeddable, but looks like hibernate does not support inheritance for Embeddable. Do you have any ideas, how my task can be achieved?
My parent class from which "Audited" entities are derived:
#Embeddable
#EntityListeners(AbstractResourceListener.class)
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class AbstractResource {
private long modifyTimestamp;
#Column(name = "_MODIFY_TIMESTAMP", nullable = true)
public long getModifyTimestamp() {
return modifyTimestamp;
}
public void setModifyTimestamp(long modifyTimestamp) {
this.modifyTimestamp = modifyTimestamp;
}
}
#MappedSuperclass is an annotation for super classes that you can extend and use in audit. Please see example

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.

Is it possible to build a JPA entity by extending a POJO?

Lets say I have the following POJO:
public class MyThing {
private int myNumber;
private String myData;
//assume getter/setter methods
}
Is it now possible to extend this POJO as a JPA entity?
#Entity
#Table(name = "my_thing")
public class MyThingEntity extends MyThing implements Serializable {
#Column(name = "my_number")
//?????????
#Column(name = "my_data")
//????????
}
I want to keep the POJO separate from the JPA entity. The POJO lives in a different project and is often used without a persistence layer, my project wants to persist it in a database and do so without the overhead of mapping from a POJO to an entity and back.
I understand that JPA entities are POJOs, but in order to use it I would have to include a library that implements javax.persistence and the other projects using the same base object have no use for a persistence layer.
Is this possible? Is this a good idea?
JPA specification states
Entities may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes.
#javax.persistence.MappedSuperclass annotation allows you to define this kind of mapping
#MappedSuperclass
public class MyThing implements Serializable {
private int myNumber;
private String myData;
// getter's and setter's
}
And
#Entity
#Table(name="MY_THING")
public class MyThingEntity extends MyThing {
}
As said by JPA specification
The MappedSuperclass annotation designates a class whose mapping information is applied to the entities that inherit from it.
And
A class designated with the MappedSuperclass annotation can be mapped in the same way as an entity except that the mappings will apply only to its subclasses since no table exists for the mapped superclass itself.
If you need to override some property defined by MyThing, use #AttributeOverride (when you want to override a single property) or #AttributeOverrides (when you want to override more than one property)
#Entity
#Table(name="MY_THING")
#AttributeOverride(name="myData", column=#Column(name="MY_DATA"))
public class MyThingEntity extends MyThing {
}
And
#Entity
#Table(name="MY_OTHER_THING")
#AttributeOverrides({
#AttributeOverride(name="myData1", column=#Column(name="MY_DATA_1")),
#AttributeOverride(name="myData2", column=#Column(name="MY_DATA_2"))
})
public class MyOtherThingEntity extends MyThing {
}
If you do not want to change your base class, you can use xml to define it as a #MappedSuperClass
Be aware: by default, the persistence provider will look in the META-INF directory for a file named orm.xml
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
<mapped-superclass class="MyThing">
</mapped-superclass>
</entity-mappings>
Nothing else. If you want to override a property, use #AttributeOverride as shown above
It is possible:
you can map it with XML - make an orm.xml (conforming to the orm schema), and map the columns of your POJO, without even extending it. It will be JPA-enabled in one environment, and a POJO in the other one
override just the getter methods and annotate them - (I'm not sure if this will work)
That said, I don't think it is necessary to do this. Just annotate your POJO, and add the compile-time dependency to your projects. Then each project will decide whether it will use them as JPA entities or not.

Categories