Create index on field from parent class - java

I have problem with adding index. I use hibernate with annotation driven configuration.
I have something like this:
#MappedSuperclass
public abstract class BaseEntity {
#Id
private String id;
private String profileId;
...
//getters and setters
}
and several child classes
#Table(name="note")
public abstract class Note extends BaseEntity{
//different fields
}
#Table(name="message")
public abstract class Message extends BaseEntity{
//different fields
}
I want to add index to field "profileId" in class BaseEntity. But if I do so, with annotation #Index(name="profileid_index"), it creates only for table "note", and fails on "message", because index "profileid_index" already exist.
I did not find way, how to make hibernate generate unique index names. Or may be someone knows another solution how to index field in parent class.

Did you have a look on #Tables annotation: http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/ ?
You can do stuff like:
#Tables(value={#Table(appliesTo="table1", indexes={#Index(name="index1", columnNames={"column1", "column2"})}),
#Table(appliesTo="table2", indexes={#Index(name="index1", columnNames={"column1", "column2"})})})
Should help in your case if you put this annotation to your #MappedSuperclass, although I don't know if there is a more cleaner solution
Being more precise, you could try for your case:
#Tables(value={#Table(appliesTo="note", indexes={#Index(name="index_profile_id1", columnNames={"profileId"})}),
#Table(appliesTo="message", indexes={#Index(name="index_profile_id2", columnNames={"profileId"})})})

Related

How to inherit from multiple base abstract classes in JPA

I faced a problem how I can create JPA entity which extends multiple base abstract classes (without creating additional table). I know there is an annotation #MappedSuperclass, but it gives an ability to create only one base class as soon as we use extends and multiple inheritance is not a Java feature.
For example, I have two bases:
#MappedSuperclass
public abstract class Authored {
#ManyToOne
private User user;
}
and
#MappedSuperclass
public abstract class Dated {
private String creationDate;
}
I expect that some of my models will extend only Authored, some -- only Dated, and some -- both.
Though it's only possible to write
#Entity
public class MyEntity extends Authored {
...
}
or
#Entity
public class MyEntity extends Dated {
...
}
Some discussions propose to inherit classes in line (e.g. Authored and AuthoredAndDated) but this seems too dirty, none of this bases logically can't extend another one.
ADDITION
I have to note that this style is supported in other frameworks like Django (due to multiple inheritance in python) so it's strange that JPA doesn't support it.
I am sorry to disappoint you, but there is no other solution than creating AuthoredAndDated as you suggested.
We faced in the same issue for our entities and went with the same procedure.
We have a
#MappedSuperclass
public class TimestampedObject {
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_at")
private Date createdAt;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_at")
private Date updatedAt;
}
and a
#MappedSuperclass
public class IdObject {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "id", updatable = false, columnDefinition = "serial")
private Long id;
}
Thus we created a TimestampedIdObject for this purpose.
Edit:
If you find another suitable solution, it would be great if you could post it here, as we have the same issue...
You should use an #Embeddable / #Embedded for goal by replacing inheritance with composition.
First, do not use #MappedSuperClass, but use #Embeddable instead for your classes you want to share the attributes with:
#Embeddable
public class Authored {...}
#Embeddable
public class Dated {...}
In the next step your Entity should not inherit from Authored or Dated but instead get an attribute referencing them:
#Entity
public class MyEntity {
#Embedded
private Authored authored;
#Embedded
private Dated dated;
}
If you want to get behaviour out of this, where you can generically access without those new attributes, you would need to introduce an interface exposing the necessary methods.
For expample if MyEntity should be able to provide details on last updates and creation, you would introduce an interface Authorable which defines to methods to access the relevant data.
public interface Authorable { /* necessary methods */ }
MyEntity will implement this interface then:
#Entity
public class MyEntity implements Authorable {
/* previous content plus implemented mehtods from interface */
}

JPA- override identity attribute in mapped super class?

I have an abstract class annotated as #MappedSuperclass. This class defines attributes common to all JPA classes such as Id.
I would like to override Id attribute mapping defined in the abstract super class and assign a sequence generator. Is it possible to override Id attribute mapping and assign a different sequence generator in JPA 2.x?
One thing that pops into my head is to use two base classes; one without the ID property and one that explicitly adds the ID property. Then you have freedom if you extend the one with ID or the one without ID so you can provide one specifically in the entity. Code skeleton without annotations:
public abstract class _Base {
// common properties here
}
public abstract class _BaseWithId extends _Base {
private Long id;
}
public class MyEntity1 extends _BaseWithId {
}
public class MyEntity2 extends _Base {
private Long id;
}

Embedded single table mapping

I'm facing an issue with modelling hibernate mapping. Here is what i have:
#Entity
#Table
public class Entry {
#Id private long id;
#Embedded private Content content;
...
}
#MappedSuperclass
#DiscriminatorColumn(name="content_type")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Content {
#Column(name="content_type") private String type;
...
}
#Embeddable
#DiscriminatorValue("A")
public class AContent extends Content {
...
}
#Embeddable
#DiscriminatorValue("B")
public class BContent extends Content {
...
}
I'd like to have that all subclasses of Content to be mapped as embedded onto the Entry class.
In other words, in result i'd like to have one Entry table with columns from all subclasses of Content.
Currently the persisting Entry test says that:
javax.persistence.PersistenceException: org.hibernate.InstantiationException:
Cannot instantiate abstract class or interface: : foo.bar.Content
So it seems that loading fails because instead of getting AContent it tries to instantiate abstract Content.
Any ideas?
Spec says...
An entity may inherit from another entity class. Entities support inheritance, polymorphic associations and polymorphic queries.
It says nothing about embeddables being inheritable and thus has no support for inheritance for them.

How to override parameter in sublass of #MappedSuperclass

I have a MappedSuperclass
#MappedSuperclass
public class A{
.
.
.
#Column(name="something")
public getSomething(){..};
public setSomething(){..};
}
I want to override the something in a subclass
#Entity
public class B{
#Override
public getSomething(){..};
}
but getting Caused by: org.hibernate.MappingException: Duplicate property mapping of data found Exception
I tried different things like "#AttributeOverride" annotation, but it didn't help.
The only solution i know is to make something Transient in the mappedSuperclass. But i don't want that it will be transient here (because there is another subclasses that don't want to override something but want that it will be transient)
Two solutions occur to me: one is to maybe break this SuperClass up and use Emmbeddeds to create the hierarchy you want. If you want to stick with this approach though, I think you need to override using #AttributeOverride both the property and the method like this in the subclass:
#Entity
public class B {
#AttributeOverride(name = "fred", column = #Column(name = "FRED"))
private Integer fred;
#Override
public Integer getFred() {return fred;}
}

MySQL tables for abstract/concrete classes using Hibernate for ORM

I have the following classes:
public abstract class Generic(){
private int Id;
...
}
public class ExtA extends Generic(){
private Generic fieldA();
private Generic fieldB();
...
}
public class ExtB extends Generic(){
private Generic fieldA;
....
}
public class ExtC extends Generic(){
...
}
Sorry for the vague example.
I am trying to find a way to save those objects to the database, but can't seem to find a good way. I wish to have separate tables for ExtA, ExtB, ExtC, and then use foreign keys to relate the contained fields. I am using MySQL, and working with Java, Spring, Hibernate. Can someone please show me an example of how to do this, or point me to some tutorial?
I should mention I am new at working with databases.
Something like this. i'm relatively sure the Table_Per_Class strategy will let you ask for any "Generic" object and query all it's subclass tables. Keep in mind if you do this, the ID should be unique across all of your subclass types. You'll have to figure out a strategy for this use the right annotations to tell hibernate what to do. But in the mean time, this example assumes you're assigning it manually before saving.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Generic {
#Id #Column(name="ID")
private Long id;
...
}
#Entity
#Table(name="EXTA")
public class ExtA extends Generic {
#Column(name="fieldA")
private Generic fieldA;
}

Categories