Generic callback methods(#PostLoad..) for inherited entity classes - JPA EclipseLink - java

My entity class hierarchy is as follows.. ClassB which extends ClassA which extends abstract mappedsuperclass AbstractClass
AbstractClass
#MappedSuperclass
public abstract class AbstractClass implements Serializable
{
}
ClassA
#Table(name = "TABLE_ONE")
#SecondaryTable(name = "TABLE_TWO",
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="Type", discriminatorType=DiscriminatorType.STRING)
#DiscriminatorValue("ClassA")
public class ClassA extends AbstractClass
{
#Column(name = "CLASSA_XML")
private String ClassAXML;
#PrePersist
#PreUpdate
public void covertObjectToXml()
{
this.ClassAXML= JAXBUtilities.marshal(Object);
}
#PostLoad
public void convertXmlToObject()
{
//does unmarshal
}
}
ClassB
#DiscriminatorValue("ClassB")
public class ClassB extends ClassA
{
#Column(name = "CLASSB_XML", table = "TABLE_TWO")
private String ClassBXML;
#PrePersist
#PreUpdate
public void covertObjectToXml()
{
this.ClassAXML= JAXBUtilities.marshal(Object);
}
#PostLoad
public void convertXmlToObject()
{
//does unmarshal
}
}
Problem : when i persist using ClassB entity. ClassA callback methods are not called and value in my classAXml attribute is not persisted.
Is there anyway to generalize callback method(i.e covertObjectToXml and convertXmlToObject) for my inherited entity class structure.. so that when i persist using
both ClassA and ClassB individually, my callback methods are called respectively based on inheritance and their values can be persisted.
Note:
I have removed the callback methods from ClassA and generalize it in
classB and persist but my requirement is mainly individual
persistent of classA and ClassB.
my call back methods should not be in mapedSuperClass i.e AbstractClass.
Thanks in advance

There are two possibilities to reuse the callback code from ClassA in ClassB:
I. The best/most elegant way is to move the whole code to a new class, say MyEntityListeners
and then to use the #EntityListeners annotation on your entity classes like
#EntityListeners(class=MyEntityListeners.class)
public class ClassB extends ClassA {
.....
}
public class MyEntityListeners {
#PrePersist
public void onPrePersist(Object entity) {
//logic with entity (check the class of the entity or you can use `ClassA` instead of `Object`)
}
}
Please note that the EntityListeners are inherited in the subclasses from superclasses, so you do not need to do anything in ClassB if the EntiyListeners are already defined in ClassA (but you can add additional EntityListeners in ClassB, that are not in ClassA). For excluding all EntityListeners from the hierarchy you can use #ExcludeSuperclassListeners
II. If you have less callback methods and a small hierarchy tree, than you could overwrite and re-annotate every callback from ClassA also in ClassB like
...
public class ClassB extends ClassA {
......
#Override
#PrePersist
public void myCallback() {
super.myCallback();
}
......
}

Related

How to control xml from super class for value and attributes using Jaxb

public class ClassA {
private ClassB classAsB;
...
}
public class ClassC {
private ClassB classCsB;
}
public class ClassB {
private String name;
private String value;
}
I have ClassA, where classAsB has name="Joe", value="None"
I would like it to serialize to
<classA><classAsB code="Joe">None</classAsB></classA>
Please note:attribute is code, not name
I have ClassC, where classCsB has name="www.si.com", value="All"
I would like it to serialize to
<classC><classCsB url="www.si.com">All</classCsB></classC>Please note: attribute is url, not name
I CANNOT annotate ClassB.
Can this be done via JaxB annotations? If so, please show how

Fasterxml: can't parse subtype from json

Problem:
Fasterxml can construct an object when it use abstraction in setters. See code below
Can not construct instance of CarState, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
Code:
#MappedSuperclass
#Inheritance(strategy= InheritanceType.SINGLE_TABLE)
public interface IState {}
public class BusState implements IState{}
//register subtype in mapper
mapper.registerSubtypes(BusState .class);
public interface Car {
public void setState(IState state);
}
#Entity
public class Bus implements Car {
private BusState state;
public void getState(BusState state) { //Seems fasterxml doesn't use this method, instead it use Car.setState
this.state = state;
}
}
I can create two different methods in Bus class: one for settingIState and one for BusState. But it looks ugly.
Question:
How can I make fasterxml to construct Bus-object correctly?

Extend JPA entity to add attributes and logic

I need to know if it's possible to add some attributes and behaviours to some POJO JPA entity (using hibernate provider) by extending it, and then to make entityManager to return extended objects instead of just pojo entitys, like the following examples:
POJO JPA Entity Class
#Entity
#Table("test")
public class Test implements Serializable {
}
Extended Class
public class ExtendedTest extends Test {
...
}
Fetching Extended Class's objects
List<ExtendedTest> extendedList = entityManager.createNamedQuery("ExtendedTest.findByFoo").setParameter("foo", "bar").getResultList();
The other possible way i'm assessing is extending funcionality with a composite entity and delegating all setters and getters, but this could mean a lot of work with huge tables:
public class ExtendedTest2 {
private Test test;
public ExtendedTest2(Test test) {
this.test = test;
}
public getFoo() {
return test.getFoo();
}
public getBar() {
return test.getBar();
}
...
}
Any suggestions will be very appreciated.
Using #Inheritance
#Entity
#Table(name="TEST")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Test {
...
}
#Entity
public class ExtendedTest
extends Test {
...
}
or #MappedSuperclass
#MappedSuperclass
public class Test {
...
}
#Entity
public class ExtendedTest
extends Test {
...
}

Java Generics. What benefit in my case?

At this moment I start work on small web application based on MVC.
Now I try implement main classes for Model layout using DAO pattern.
So, first of all I create two entity classes (for example): Author and Book:
package myProject.model.entity;
import java.io.Serializable;
public class Author implements Serializable {
private static final long serialVersionUID = 7177014660621405534L;
private long id;
private String firstName;
private String lastName;
public Author() {
}
// getter and setter methods here
}
and Book class:
package myProject.model.entity;
import java.io.Serializable;
public class Book implements Serializable {
private static final long serialVersionUID = 7177014660621405534L;
private long id;
private String title;
private String description;
public Book() {
}
// getter and setter methods here
}
On next step, I see, that classes Book and Author both have getId() and setId().
so, I create interface Persistent for my Entity classes:
package myProject.model.entity;
public interface Persistent {
public long getId();
public void setId(long id);
}
So, first my question:
It is correct implementation for model package?
On the next step, I start implement classes for package dao.
package myProject.model.dao;
import java.util.List;
import myProject.model.entity.Persistent;
public interface Dao {
Persistent get(long id);
void save(Persistent persistent);
void delete(long id);
}
Next step: create interfaces AuthorDao and BookDao, that extend base dao interface Dao
But both interfaces: AuthorDao and BookDao - at this moment empty.
What do you think - it in normal, that interfaces empty? It is my second question.
And on the last step I create package model.dao.hibernate and add to the package to class AuthorDaoHibernate and BookDaoHibernate - both class implements AuthorDao and BookDao interfaces.
And My main question now:
my interface Dao work with objects type Persistent and I dont use Generics. And all ok and nice.
What do you thinks - what benefits I have, if I re-work Dao interface wit Generics:
package myProject.model.dao;
import java.util.List;
import myProject.model.entity.Persistent;
public interface Dao<Persistent> {
T get(long id);
List<T> getAll();
void save(T persistent);
void delete(long id);
}
My Dao classes work only with persistent entities - no any other object type...
Do you really any reasons in me case use Generics?
Generics can greatly improve code readability and reduce errors that could come from wrong casting.
We're using something similar to what you described (note that there are interfaces and implementations needed).
Here's a basic example (I'll leave the getters and setters out for brevitiy):
#MappedSuperClass
class BaseEntity {
#Id
private int id;
}
#Entity
class UserEnity extends BaseEntity {
//user stuff like name
}
class BaseDAO<T extends BaseEntity> {
public T findById(int id) {
...
}
//other generic CRUD methods
}
#Stateless
class UserDAO extends BaseDAO<UserEntity> {
//additional user specific methods
}
Using UserDAO would then be like this:
UserDAO userDao; //some injection or lookup
//no explicit cast needed here, thanks to generics
UserEntity user = userDao.findById(userId);
//compiler error due to the generic parameter being UserEntity and AnotherEntity doesn't extend that
AnotherEntity a = userDao.findById(someId);
If you want to use generics you should define Dao as following:
public interface Dao<T extends Persistent> {
.....................
void save(T persistent);
...................
}
Now when you extend it you will have to create save that accepts Book only:
public class Book extends Dao<Book> {
.....................
void save(Book persistent);
...................
}
The benefit here is that you cannot pass Author to BookDao. This will not pass compilation.
BTW if you are using Hibernate, JPA or other ORM solution you do not really have to create DAO per entity. One generic dao can solve all your needs.
There is no reason here. If it's unique, it's not generic, by definition !
List getAll() will do the Job.
The ArrayList is Generic because it will sometimes return Persistent, sometime President.

Dynamic Inheritance - Java

Dynamic Inheritance
I have a situation where I want a class (which is a JPA entity) to be able to extend either class A or class B dynamically. My thought was to use Generics, but it looks like generics doesn’t support this. For example:
#Entity
public abstract class Resource() {
...
}
#Entity
public abstract class Snapshot() {
...
}
public abstract class CommonRS<R extends Resource, S extends Snapshot> {
/* This is the class that I want to dynamically assign Inheritance to. */
...
}
#Entity
public class FeedResource extends CommonRS<Resource> {
...
}
#Entity
public class FeedSnapshot extends CommonRS<Snapshot> {
...
}
The reason I want to do this is that FeedResource must Inherit from Resource and FeedSnapshot must inherit from Snapshot because both classes are using the JPA join strategy InheritanceType.JOINED and are persisted to different tables, however they both share common attributes and I would like them to be able to inherit those common attributes.
I understand that I can I could use #Embeddable on CommonRS and the Embed it in both FeedResource and FeedSnapshot.
Since Java doesn’t support multiple inheritance, I can’t see any other way to do this other than using Embeddable.
Thanks in advance.
Here is how you do it
#MappedSuperClass
public abstract class Base() {
...
// put your common attributes here
}
#Entity
public abstract class Resource() extends Base{
...
}
#Entity
public abstract class Snapshot() extends Base {
...
}
public abstract class CommonRS<R extends Base> {
...
}
#Entity
public class FeedResource extends CommonRS<Resource> {
...
}
#Entity
public class FeedSnapshot extends CommonRS<Snapshot> {
...
}
UPDATE
Another solution can be implementing same interface (if common inheritance cannot be achieved). In that case #MappedSuperClass annotation should be used on actual base classes.
#Entity
public abstract class Resource() extends BaseIntf {
...
}
#Entity
public abstract class Snapshot() extends BaseIntf {
...
}
public abstract class CommonRS<R extends BaseIntf> {
...
}
#Entity
public class FeedResource extends CommonRS<Resource> {
...
}
#Entity
public class FeedSnapshot extends CommonRS<Snapshot> {
...
}

Categories