JPA-override annotation on SuperClass property - java

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).

Related

Using javax #Transient annotation with a field of MappedSuperclass

Javax's #Transient annotation when applied over an #Entity class' field will prevent the annotated field from being persisted into the database as a column. Is there a method to selectively achieve this behavior (of excluding the persistence of a certain column) for a field in a MappedSuperclass?
To clarify, I want some field x present in a MappedSuperclass to be persisted for some entity classes that extend the MappedSuperclass and excluded from persistence in some other extending entity classes.
I have tried shadowing the field x in the extending class and annotating it with #Transient, however, this doesn't seem to work. Is there any alternative approach that would enable this behavior?
Yes. In the children entity class that extends #MappedSuperclass , you can configure it to use the property access for this transient field .
So assuming a given #MappedSuperclass has a #Transient field :
#MappedSuperclass
public abstract class Parent {
#Transient
protected LocalDateTime createdTs;
}
For the children entity that want to include this transient field , you could do :
#Entity
#Table(name = "foo")
public class Foo extends Parent {
#Id
private Long id;
#Access(AccessType.PROPERTY)
#Column(name= "createTs")
public LocalDateTime getCreatedTs() {
return this.createdTs;
}
}
And for the children entity that want to exclude this transient field , you could do :
#Entity
#Table(name = "foo")
public class Foo extends Parent {
#Id
private Long id;
}

Objectbox inherit properties from base class (which is NOT an entity itself)

I have a simple base class in which I want to have some common fields, like id etc. The base class is not an Entity by itself.
public class Base {
#Id
protected long id;
protected String someOtherCommonProperty;
}
And I have an entity class, extending the base class.
#Entity
public class Entity extends Base {
String name;
String address;
}
I would expect the entity class to inherit the fields from the base class, but what I get is
[ObjectBox] No #Id property found for 'Entity', add #Id on a not-null long property.
Is there any way to fix that, besides using interfaces and have a lot of duplicated code?
You can use the #BaseEntity annotation.
Have a look at the documentation: Objectbox - Entity Inheritence.
Shameless copy for future reference:
In addition to the #Entity annotation, we introduced a #BaseEntity annotation for base classes, which can be used instead of #Entity.
There three types of base classes, which are defined via annotations:
No annotation: The base class and its properties are not considered for persistence.
#BaseEntity: Properties are considered for persistence in sub classes, but the base class itself cannot be persisted.
#Entity: Properties are considered for persistence in sub classes, and the base class itself is a normally persisted entity.
Example:
// base class:
#BaseEntity
public abstract class Base {
#Id long id;
String baseString;
public Base() {
}
public Base(long id, String baseString) {
this.id = id;
this.baseString = baseString;
}
}
// sub class:
#Entity
public class Sub extends Base {
String subString;
public Sub() {
}
public Sub(long id, String baseString, String subString) {
super(id, baseString);
this.subString = subString;
}
}

Map Collection of Interface using annotation in Hibernate

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.

Override JPA MappedSuperClass generic property

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

Mapping Multiple Classes to a Table in Hibernate, Without a DTYPE Column

I have two hibernate classes: a base class, and an extended class that has additional fields. (These fields are mapped by other tables.)
For example, I have:
#Entity
#Table(name="Book")
public class A {
private String ID;
private String Name;
// ...
}
#Entity
#Table(name="Book")
public class B extends A {
public String node_ID;
// ...
}
public class Node {
public String ID; // maps to B.node_ID
// ...
}
How do I map this in Hibernate? The hibernate documentation states three types of inheritence configurations: one table per class, one table with a type column, and a join table -- none of which apply here.
The reason I need to do this is because class A is from generic framework that's reused over multiple projects, and class B (and Node) are extensions specific to one project -- they won't be used again. In the future, I may have perhaps a class C with a house_ID or some other field.
Edit: If I try the above pseudo-code configuration (two entities mapped to the same table) I get an error that the DTYPE column doesn't exist. The HQL has a "where DTYPE="A" appended.
This is possible by mapping the #DiscriminatorColumn and #DiscriminatorValue to the same values for both classes; this can be from any column you use that has the same data regardless of which type (not sure if it works with null values).
The classes should look like so:
#Entity
#Table(name="Book")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="published")
#DiscriminatorValue(value="true")
public class A {
private String ID;
private String Name;
// ...
}
#Entity
#Table(name="Book")
#DiscriminatorValue(value="true")
public class B extends A {
public String node_ID;
// ...
}
For anyone who got here like me and does not want to have the dtype column but instead want to use the same table for more than one entity as is I would recommend using this
Basically you can create a Base like this
#MappedSuperclass
public abstract class BaseBook<T extends BaseBook> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
... any other variables, getters + setters
}
#Entity
#Table(name= "book")
public class BookA extends BaseBook<BookA>{
//Default class no need to specify any variables or getters/setters
}
#Entity
#Table(name= "book")
public class BookB extends BaseBook<BookB>{
#Column(name = "other_field")
private String otherFieldInTableButNotMapedInBase
... Any other fields, getter/setter
}
From the above we have created base super class which does not have any entity or table mapping. We then create BookA to be default with the Entity + Table mapping. From there we can create other Entities all extending from BaseBook but pointing to one table

Categories