How to get a class object in #PrePersist method - java

This is my class
public class Customer{
private String programId;
private String entityName;
private String columnName;
#PrePersist
doSomething(){
doSomeService.newMethod(//how can I pass class object here with all its values);
}
}
I want to access few attributes of class in my prepersist to do some logic , is it possible to get class object with its values inside PrePersist method

You can use it like below
#PrePersist
private void beforeSave( Customer customer )
{
}

Related

Map Entity to the correct subclass

I have the following classes Entity, BaseClass, SubClass1, SubClass2.
public class Entity {
private String field1;
private String field2;
private String type;
private String field3;
private String field4;
}
public class BaseClass {
private String field1;
private String field2;
private String type;
}
public class SubClass1 extends Base {
private String field3;
}
public class SubClass2 extends Base {
private String field4;
}
Entity is obtained from by call an API. Depending on the value of the type property of the BaseClass, I want to map the Entity to the corresponding subclass.
One option I can think of mapping is below,
#Mapper
public interface EntityMapper {
SubClass1 mapEntityToSubClass1(Entity entity);
SubClass2 mapEntityToSubClass2(Entity entity);
}
I will invoke either of the methods mapEntityToSubClass1 or mapEntityToSubClass2 conditionally based on the type in my business logic. Since I will be getting a List from the external API, looping through, checking the type in Entity doesn't seem good to me. In my business logic there are currently 4 subclasses and in future there can be more and the logic becomes more clumsy.
Is there a better way of implementing the same in mapstruct?
Not sure if I understand correctly, but you just want to pick which subclass to map to based on a field in the source? Don't do that in the business logic, simply use a default method. Something like this:
#Mapper
public interface EntityMapper {
default BaseClass map(Entity entity) {
if(entity.getType().equals("a"))
return mapEntityToSubClass1(entity);
if(entity.getType().equals("b"))
return mapEntityToSubClass2(entity);
throw new RuntimeException("Unsupported base type");
}
Sub1 mapEntityToSubClass1(Entity entity);
Sub2 mapEntityToSubClass2(Entity entity);
}

I'm not able able access the method of class

I have the class which has to details inside the data http://www.mocky.io/v2/5cacde192f000078003a93bb , i have written a class to get the data and next class to get the details
public class ApiObject {
#SerializedName("status")
#Expose
public String status;
#SerializedName("data")
#Expose
public List<MyData> data = null;
#SerializedName("products")
public List<Products> products = null;
public List<MyData> getData() {
return data;
}
public class MyData{
#SerializedName("details")
public Details details;
#SerializedName("product_count")
public Integer productCount;
public Details getDetails(){
return details;
}
#SerializedName("product_count")
#Expose
private String Product_count;
#SerializedName("products")
public List<Products> getProducts(){
return products;
}
//setter and getters
}
I have created a object of Apiobject in more class
and I'm trying to access the getDetails method
like
ApiObject apiObject ;
apiObject.getData().getDetails();
I'm getting an error cannot resolve a method
getDetails() is a private method. Therefore, can only be accessed from within the class MyData. Make it public for it to be accessible to instances of other classes.
There are two problems in your code:
getDetails() is a private method, make it public if you want to access it.
getData() return a list of MyData objects, not a single instance. So, you should iterate through the list if you want to call the getDetails().
for (MyData data : apiObject.getData()) {
data.getDetails();
}

How to pass a variable from 2 different POJOs?

I got 2 POJOs that are being passed to a HttpEntity and converted to json.
Before passing them i need a variable which is in both of the POJOs with different names because of the needs of the API so i cant change them.
What is the best way without casting and in terms of OOP also within the POJO definition like mentioned in Wikipedia?
Abstract pojo
public abstract class Pojo{
//some common variables
//setter getters
}
PojoOne
public class PojoOne extends Pojo{
private String id;
//setter getter for id
}
PojoTwo
public class PojoTwo extends Pojo{
private String identifier;
// setter getter for identifier
}
Class that
public class SomeOtherClass {
public void getIdForUse(Pojo pojo){
String s = pojo. // How should this be to have ability to get both id and identifier
}
}
Add a common method to the common superclass:
public abstract class Pojo {
public abstract String getId();
// some common variables
// setter getters
}
public class PojoOne extends Pojo {
private String id;
#Override
public String getId() {
return id;
}
//setter for id
}
public class PojoTwo extends Pojo {
private String identifier;
// setter getter for identifier
#Override
public String getId() {
return identifier;
}
}

Mapping abstract class in dozer

I have the following class structure (it actually is a VO layer with Hibernate mappings):
public abstract class abstractClassVO {
private int id;
private String name;
}
public class concreteClassAVO extends abstractClassVO {
private String aAttribute;
}
public class concreteClassBVO extends abstractClassVO {
private Long bAttribute;
}
And the equivalent DTO objects:
public abstract class abstractClassDTO {
private int id;
private String name;
}
public class concreteClassADTO extends abstractClassDTO {
private String aAttribute;
}
public class concreteClassBDTO extends abstractClassDTO {
private Long bAttribute;
}
Then I have another object like this:
public class compositeObject {
private int anAttribute;
private abstractClassVO myInstance;
}
and its equivalent:
public class compositeObjectDTO{
private int anAttribute;
private abstractClassDTO myInstance;
}
How can I tell dozer to automatically map myInstance to the specific DTO that corresponds to the concrete class implementation in the VO layer?
Currently, out of the box, Dozer isn't even putting anything in the myInstance field of the compositeObjectDTO class. My guess is that it's due to the fact that abstractClassDTO it is an abstact class, and since it cannot determine the implementation, it does nothing. I am not getting any exceptions.
Dozer can't do it out of the box but you could write a helper that would determine destination class by source class. You can get this information from DozerBeanMapper.getMappingMetadata().getClassMappings* methods. These methods return list of ClassMappingMetadata that contains destination class. You just only need to chech whether destination class is inherited from abstractClassDTO. This check can be omitted if you only have one mapping for one VO.
For bi-directional mapping you should additionally check ClassMappingMetadata.MappingDirection field.

Getting object field previous value hibernate JPA

Let's assume I have this class :
#EntityListeners({MyListener.class})
class MyClass {
String name;
String surname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return name;
}
public void setSurname(String name) {
this.name = name;
}
public void save() {
JPA.em().persist(this);
return this;
}
public void update() {
JPA.em().merge(this);
}
public static MyClass findById(Long id) {
return JPA.em().find(MyClass.class, id);
}
}
Now in my MyListener class I'm trying to figure out the previous value MyClass instance versus the new value that is about to get saved(updated) to database. I do this with preupdate metdhod :
#PreUpdate
public void preUpdate(Object entity) {
...some logic here...unable to get the old object value in here
}
So assuming I have a MyClass objects instance with name and surname :
MyClass mycls = new MyClass();
mycls.setName("Bob");
mycls.setSurname("Dylan");
mycls.save();
This wasn't picked up by listener which is ok because I'm listening only to updates.
Now if I were to update this instance like so :
MyClass cls = MyClass.findById(someLongId)
cls.setSurname("Marley");
cls.update();
So this triggers the preUpdate method in mylistener and when I try to :
MyClass.findById(someLongId);
When I debug I already get the newly updated instance but the update hasn't happened yet because when I check in database in column surname it's still Dylan.
How do I get the value from database in my preUpdate method and not the one I just updated?
I think an easy way is to save the previous value in a transient variable that JPA will not persist.
So just introduce a variable previousSurname and save the actual value before you overwrite it in the setter.
If you want to save multiple properties it would be easy if your class MyClass is Serializable.
If so add a post load listener
public class MyClass implements Serializable {
#Transient
private transient MyClass savedState;
#PostLoad
private void saveState(){
this.savedState = SerializationUtils.clone(this); // from apache commons-lang
}
}
But be aware that the savedState is a detached instance.
You can then access the previous state in your EntityListener.
You can also move the PostLoad listener to the EntityListener class. But then you need access to the savedState field. I recommend to make it either package scoped or use a package scoped accessor and put MyClass and MyListener in the same package,
public class MyListener {
#PostLoad
private void saveState(MyClass myClass){
myClass.saveState(SerializationUtils.clone(myClass)); // from apache commons-lang
}
}
public class MyClass implements Serializable {
#Transient
private transient MyClass savedState;
void saveState(MyClass savedState){
this.savedState = savedState;
}
}

Categories