I have the below scenario, I need sub-classes to be able to specify the actual types of properties found in MappedSuperClass(s). I use hibernate as a provider and I don't mind using hibernate specific annotations to solve this problem.
#MappedSuperclass
abstract class BaseA{
....
#OneToMany(mappedBy = "baseA")
public Set<? extends BaseB> getBaseB(){
.....
}
}
#MappedSuperclass
abstract class BaseB{
.....
#ManyToOne(optional = false)
#JoinColumn(name = "basea_id")
public BaseA getBaseA(){
.....
}
}
#Entity
class BaseAImpl extends BaseA{
public Set<BaseBImpl> getBaseB(){
.....
}
}
#Entity
class BaseBImpl{
public BaseAImpl getBaseA(){
.....
}
}
#AssociationOverride will hep you in this case. See the documentation for it (of course it is a JPA annotation). You could use it in combination with the #AttributeOverrides annotation for overriding basic types. Example (taken from the example):
#MappedSuperclass
public class Employee {
...
#ManyToOne
protected Address address;
...
}
#Entity
#AssociationOverride(name="address",
joinColumns=#JoinColumn(name="ADDR_ID"))
// address field mapping overridden to ADDR_ID foreign key
public class PartTimeEmployee extends Employee {
...
}
Related
How can I tell hibernate to ignore a field during schema auto generation?
In this special case: the field is inherited from a parent abstract class, so I cannot just comment it out!
I tried using #Transient, but the field is still autogenerated in the schema.
#MappedSuperclass
public abstract class BaseEntity {
private String someField;
//getter+setter
}
#Entity
public class MyEntity extends BaseEntity {
#Transient //I want to ignore this field during hibernate.ddl.auto
#Override
public String getSomeField() {}
}
Add the Transient annotation in the super class:
#MappedSuperclass
public abstract class BaseEntity {
#Transient
private String someField;
}
#Entity
public class MyEntity extends BaseEntity {
}
Is it possible to map a baseTable with a base class and tell to JPA tool to not insert in the class the fileds that are in the baseTable?
I have the field creation-date which i want in every table of my db, so i created a baseTable with that field and the other tables extend this baseTable.
When i generate the classe for mapping this structure, japtool creates for me each table with creation-date field, which clearly i'd want just in baseEntity class and not in every child class.
There is a way to accomplish it?
If I understood your answer correctly, I think you are looking for JPA Inheritance
#MappedSuperclass
public class BaseEntity {
#Id
protected Integer id;
protected Date createdDate;
...
}
#Entity
public class EntityA extends BaseEntity {
protected String otherAttribs;
...
}
#Entity
public class EntityB extends BaseEntity {
protected Float differentAttribs ;
...
}
I have SuperClass where I have defined my properties and I want to apply one more annotation on one of the SuperClass Property.
#MappedSuperclass
public class CartBaseEntity {
private String cartName;
#Column(name = "cart_name")
public String getCartName() {
return cartName;
}
public void setCartName(String cartName) {
this.cartName = cartName;
}
}
And my Sub Class is in below:
#Entity
#Table(name = "CART2")
public class CartEntity extends CartBaseEntity implements Serializable {
private Set<Items> items;
#Basic(fetch = FetchType.LAZY)
#Override
public String getCartName() {
return super.getCartName();
}
}
I was trying to override the 'cartName' column and want to add #Basic annotation on it. Is it possible or is there any workarround? TIA
Yes, it's possible with #AttributeOverride annotation applied to a subclass:
#Entity
#Table(name = "CART2")
#AttributeOverride(name = "cartName", column = #Column(name="CART_NAME"))
public class CartEntity extends CartBaseEntity implements Serializable {
...
}
UPDATE: here's what JPA 2.1 Specification tells about overriding a column in a mapped superclass:
11.1.4 AttributeOverride Annotation
The AttributeOverride annotation is used to override the mapping of
a Basic (whether explicit or default) property or field or Id
property or field.
The AttributeOverride annotation may be applied to an entity that
extends a mapped superclass or to an embedded field or property to
override a Basic mapping or Id mapping defined by the mapped
superclass or embeddable class (or embeddable class of one of its
attributes).
I have an interface called Rule with 2 implementing classes who all share one Abstract base class.
#MappedSuperclass
public interface Rule { .. }
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseRule implements Rule {
#Entity
public class ImlementingRule1 extends BaseRule {
#Entity
public class ImlementingRule1 extends BaseRule {
I'm using this Rule interface in a containgRules class as such:
#OneToMany
#JoinColumn(name = "RULES_ID")
private List<Rule> rules;
Whatever setup I try I always end up with:
Caused by: org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: mynamespace.BaseRule
I personally have found no other solution than to use the abstract base class, instead of interface.
#OneToMany
#JoinColumn(name = "RULES_ID")
private List<BaseRule> rules;
It states right here:
Annotating interfaces is currently not supported.
I want to persist my litte zoo with Hibernate:
#Entity
#Table(name = "zoo")
public class Zoo {
#OneToMany
private Set<Animal> animals = new HashSet<Animal>();
}
// Just a marker interface
public interface Animal {
}
#Entity
#Table(name = "dog")
public class Dog implements Animal {
// ID and other properties
}
#Entity
#Table(name = "cat")
public class Cat implements Animal {
// ID and other properties
}
When I try to persist the zoo, Hibernate complains:
Use of #OneToMany or #ManyToMany targeting an unmapped class: blubb.Zoo.animals[blubb.Animal]
I know about the targetEntity-property of #OneToMany but that would mean, only Dogs OR Cats can live in my zoo.
Is there any way to persist a collection of an interface, which has several implementations, with Hibernate?
JPA annotations are not supported on interfaces. From Java Persistence with Hibernate (p.210):
Note that the JPA specification
doesn’t support any mapping annotation
on an interface! This will be resolved
in a future version of the
specification; when you read this
book, it will probably be possible
with Hibernate Annotations.
A possible solution would be to use an abstract Entity with a TABLE_PER_CLASS inheritance strategy (because you can't use a mapped superclass - which is not an entity - in associations). Something like this:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractAnimal {
#Id #GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
...
}
#Entity
public class Lion extends AbstractAnimal implements Animal {
...
}
#Entity
public class Tiger extends AbstractAnimal implements Animal {
...
}
#Entity
public class Zoo {
#Id #GeneratedValue
private Long id;
#OneToMany(targetEntity = AbstractAnimal.class)
private Set<Animal> animals = new HashSet<Animal>();
...
}
But there is not much advantages in keeping the interface IMO (and actually, I think persistent classes should be concrete).
References
Annotations, inheritance and interfaces
using MappedSuperclass in relation one to many
Polymorphic association to a MappedSuperclass throws exception
I can guess that what you want is mapping of inheritance tree.
#Inheritance annotation is the way to go.
I don't know if it will work with interfaces, but it will definitely work with abstract classes.
I think you have to annotate the interface too with #Entity and we have to annotate #Transient on all getters and setters of interface.