Hibernate mapping of derived class with no fields - java

I've encountered situation when I need two classes have same fields, but a slightly different behavior, one of them possess some other field, but another doesn't, so the questions is : do i have to map derived class which have no special fields?
Here's example, let's say i have class A, and class B, both have to have some collection(e.g. of C objects) and some other field D, so i create abstract class AB, which is their parent, and while class B also have String field, class A - doesn't, and all of them are descendants of M, which have someMethod():
abstract class M {
//fields, getters, etc
public void someMethod(){
//doSmth
}
}
abstract class AB extends M {
private D d;
private Set<C> cs;
//getters, setters, etc
}
class A extends AB{
#Override
public void someMethod(){
for(C c : cs){
//doSmth
}
}
}
class B extends AB {
private String text;
//getters etc
}
So, I definitely should map M, AB and B, but should i map A?
P.S. we use xml mappings

If you want Hibernate to return you List<A> as a query result, yes you'd need to map A.

Related

Exclude inner class fields using JsonInclude.Include.NON_DEFAULT

#JsonInclude(JsonInclude.Include.NON_DEFAULT)
I have a nested class structure as follows:
public class A{
String z;
String y;
float p;
List<B> b;
public static class B{
String x;
String w;
float q;
List<C> c;
public static class C{
String v;
String u;
float r;
}
}
}
I have another class as follows:
public class D{
List<B> b;
}
In my use case, I am returning class D as part of an API call. String x(in class B) and String v(in class C) will always be non-null. But String w and String u may or may not be null. I want to exclude null fields and default fields ( like 0.0 for float q and float r) from my response and therefore want to use #JsonInclude(JsonInclude.Include.NON_DEFAULT). But I don't want this to happen for all use cases, but only for my use case, i.e. only for class D? Is the following an effective way of achieving it?
#JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class D{
List<B> b;
}
Will the above way work on the inner classes as well? Please feel free to suggest another method because I'm unable to think of one.

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);
}

JAXB unmarshal child attributes without creation of child class

I want to unmarshal a (simplified) XML structure like this:
<parent>
<a>AValue</a>
<b>BValue</b>
<c someAttribute = "true">CValue</c>
</parent>
I know how to do this with declaring a class C like this:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "c", propOrder = {
"someAttribute"
})
public class C{
#XmlValue
private String c;
#XmlAttribute ( name="someAttribute")
private boolean someAttribute;
//getters and setters
}
And getting it as a member in class parent like this:
public class Parent{
private String a;
private String b;
private C c;
//getters and setters for c,b,a
}
This works finde and i can access the value of C via parent.getC().getC();
My Question is how to achieve that i do not have to create a class C and get the value and attribute of C as a member of parent, without editing the parent Pojo with new members and other getters and setters.
I already tried to do this via Listeners and searched for similar structures, but i haven't got any ideas left.
I finally figured out how to achieve this.
Its necessary to use the #XmlJavaTypeAdapter Annotation and mark the C class as an #XmlRootElement as well as an #XmlAccessorType(XmlAccessType.FIELD).
Furthermore one need to use the #XmlTransient on the getter of the String member which was annotated with #XmlJavaTypeAdapter.
Full solution:
Class C:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class C{
#XmlValue
private String c;
#XmlAttribute
private boolean someAttribute;
//getters and setters for both
Class Adapter:
public class Adapter extends XmlAdapter<C, String> {
public String unmarshal(C pC) throws Exception {
//some possible handling with the attribute over pC.getSomeAttribute();
return pC.getC();
}
public C marshal(String pC) throws Exception {
C c = new C();
c.setC(pC)
//some possible handling to set the attribute to c
return c;
}
Class Parent:
public class Parent{
private String a;
private String b;
#XmlJavaTypeAdapter(Adapter.class)
private String c;
#XmlTransient
public String getC() {
return c;
}
//getters and setters for b,a and setter for C
}

Best way to write pojos that can have common fields

I am currently making a service in which there are lots of public API's. And the response and request objects overlap a lot. So, I was thinking that is there a way by which we can generalise the pojo creation for the request/response objects.
Sometimes the response object is identical to the request object with one or two extra fields.
Let me give you an example.
#Data
public class Request {
private A objA;
private B objB;
}
#Data
public class Response {
private A objA;
private B objB;
private C objC;
}
#Data
public class A {
private D objD;
}
#Data
public class B {
private String sB;
private E obje;
}
#Data
public class C {
private String sC;
}
Similary, D and E are pojos as well. The thing is that there is a lot of similarity(overlapping fields) in request/response objects.
Your solution is probably inheritance: Create a parent abstract object type with the overlapping fields and have the request and response objects extend it and specify any extra (unique) fields they need.
Inheritence
public abstract class Common {
private String overlapfield1;
private String overlapfield2
}
public class Request extends Common {
private String requestField1;
private String requestField2;
}
public class Response extends Common {
private String responseField1;
private String responseField2;
}
You could also approach this using composition: Create an object type with the overlapping fields and include this object as a sub-object of the Request/Response types:
Composition
public class Common {
private String overlapfield1;
private String overlapfield2
}
public class Request {
private String requestField1;
private String requestField2;
private Common common;
}
public class Response {
private String responseField1;
private String responseField2;
private Common common;
}
There are pros and cons to each approach which are widely discussed on this and other boards. These however, are the two standard approaches to dealing with such a problem.
It really depends on what you are trying to achieve. I don't see it being a huge problem repeating the fields but you've given an abstract use case rather than a real world situation where I can understand what you're trying to achieve.
Perhaps you want to pass your #Data objects to the same services? In which case you might want to use interfaces because a class can implement multiple interfaces.
Eg
public interface AContiner {
A getA();
void setA(A a);
}
public interface BContiner {
B getB();
void setB(B b);
}
#Data
public class Bean1 implements AContainer {
private A a;
}
#Data
public class Bean2 implements AContainer, BContainer {
private A a;
private B b;
}
public class MyFantasticService {
public void doStuffWithA(AContainer data) {
System.out.println(data.getA());
}
public void doStuffWithB(BContainer data) {
System.out.println(data.getB());
}
}

How to avoid duplicate code in the translation objects?

I have a super class named Transformer. and I have two derived classes that converts class A to B and vice versa. There is the classes :
class A{
private Long id;
private String name;
... getter and setters
}
class B{
private Long id;
private String name;
... getter and setters
}
interface Transformer<S,D> {
D convert(S source);
}
class ATransformer implements Transformer<A,B>{
public B convert(A a){
B b=new B();
b.setId(a.getId());
.....
return b;
}
}
class BTransformer implements Transformer<B,A>{
public A convert(B b){
A a=new A();
a.setId(b.getId());
.....
return a;
}
}
as you see, derived transformer classes have duplicate codes. Is there any design or solution to avoid this duplication without using reflection?
You can use a bean mapper framework like Dozer or orika to do the work for you (and spare you the duplicate code).
However as already mentioned in the other comments, it is (in most cases) preferable to avoid having classes that are nearly the same without them being in the same class hirarchy and therefore castable.

Categories