How to Avoid Annotations in POJOs - java

lets say i have the following POJO Class
public class Example {
private String name;
private int id;
private Object o;
// more fields
// getter/Setter
Now lets assume i want to persist my Entity using JPA i will come on with the following example POJO Class:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private int id;
#OneToMany(mappedBy = "directive")
private String name;
In my Opinion this is bad, becaus if i want to use e.g. Spring Data MongoDB the Annotations would be useless/false.
The only why i can think of to avoid this, is defining an Interface or an Abstract class, for example Storable, which defines getter/setter methods.
But then i have violated the POJO definition (and one can argue it was not a Pojo to begin with).
Are there any best Practices for defining Model Classes?

When using JPA, you can leave you classes untouched and have ALL your configuration in XML files. Many people prefer annotations, but if changing the persistence implementation is a requirement, you should consider using external configuration.
I am not sure about other frameworks/specs besides JPA, but XML configuration goes a long way in java. I am sure, many frameworks offer such possibilities.
There is also a pattern called DTO (data transfer objects) that can be used for separation of persistence concerns from business concerns.
The gist is: you use your annotated, DB-centric classes for your DB connection only. Your main application only uses business-oriented classes and is persistence-agnostic. The data could come from a DB or from a flat file, as long as you can convert it to you business objects, all is well.
EDIT: DTOs sound like a lot of work, but you gain clarity and testability by separating concerns. hexagonal architecture and clean architecture emphasize this approach.

Related

JPA: Is there some way to implement inheritance for Embeddable

Here is the example code:
class Resource {
Long id;
#Embedded
GPU gpu;
CPU cpu;
}
abstract class GPU {
String name;
GpuType type;
}
class PhysicalGPU extends GPU {
}
class VirtualGPU extends GPU {
private int partition;
}
I have an Entity Resource and it has a field GPU which is a superclass. It can be a VirtualGPU or PhysicalGPU. But JPA or Hibernate seems not support class inheritance for #Embedded fields. And it is ugly to create a single GPU type with no inheritance or create PhysicalGPUResource and VirtualGPUResource to implement the inheritance for a single field.
And I think as a descriptor of a Resource, make the GPU be an association in a seperate table (and give a ManyToOne relation in Resource) is also not a good practice but this will make the Inheritance available.
I did some search and I think right now the answer is no. But I still think this is a quite big requirement for the Hibernate ORM and it can be implemented in some framework like MyBatis, it is quite weird that Hibernate do not support this behavior. So maybe there is some other way to make this done?
I think current the best way is using UserType. Follow the article Custom Types in Hibernate and the #Type Annotation can be very helpful.
But I still don't know what is the advantage of the CompositeUserType.

Is it possible to map custom final classes in hibernate?

Suppose I have already made class which I wish to persist. I can't change it's code, i.e. can't put any annotations inside. Also, class is not following bean convention.
I.e. it is arbitrary complex class I wish to persist.
Is it possible to write some sort of custom serializer and deserializer (don't know how to name it) in Hibernate, so that I be able to read these classes as usual POJOs?
Hello the first question is can I map a "fina class" the answer to this question is YES as long as you dont use Hibernate Enchancing or some sort of instrumentation.
Now second question. Bean not following Bean Conventions. I guess this means no getters and setters. You can have Attribute level access so this is again not a problem.
Is it possible to write custom serializer in Hibernate. The answer here is NO. Why ? Because Hibernate is not about Serialization hibernate is about SQL. There is no strict requirement that a Hibernate Entity should be serialize-able.
Even though Hibernate does not enforce serialization. Can I still make my final class serialize-able even though it does not implement Serializable or Eternalizeable. Yes you need to wrap it into class implementing Serializable or Externalizeable and implement the doRead doWrite methods yourself.
Serialization to JSON or XML - this is not part of Hibernate neither is part of JPA. Serialization to these two formats is defined as part of the Jaxb and Jax-rs specifications.
Have a look at hibernate UserType and CompositeUserType, with the well known EnumUserType example
Enums are a bit like your needs : final class, no getters nor setters. They are not complex though, so you might need a CompositeUserType that allows to map several columns for one Type, rather that a UserType.
Then you would use it like that in your class :
public class MyClass {
#Id
private Long id;
#Type(type = "com...MyCompositeUserType")
private ComplexFinalClassNotPojo complexObject;
}

JPA Inheritance mapping - Making a field optional in 1 subclass, mandatory in another

I have a entity in the application I am working for that has two versions.
I have mapped the entity using JPA inheritance mapping so that there are now two classes, let's call them Contract and OtherContract. They both have a couple of shared fields, defined in BaseContract. Both classes inherit from that base class.
The problem now is that of those shared fields, some should be mandatory (as in have a not null constraint in the database) in the "Contract" class but optional in "OtherContract".
What I could do is duplicate all of the fields from the shared class in both classes and modify the annotations accordingly but that seems hard to manage.
(like this:)
public class Contract extends BaseContract {
#Column(nullable = true)
private String name;
}
public class OtherContract extends BaseContract {
#Column(nullable = false)
private String name;
}
I could also make all the fields non-mandatory and add the validation in my domain layer (which I'll do anyway). I like this a little better but the database tables will have all the fields optional which I don't like.
The inheritance type I will probably have to use is TABLE_PER_CLASS
Does anyone know a solution without these drawbacks?

Is is possible to create a combo-annotation which combines multiple field annotations?

I have some boolean fields in my JPA entities which are annotated in the following way:
#Column(length = 1)
#Type(type = "yes_no")
private final boolean myField;
Is it possible to create a combo-annotation (e. g. MyAnnotation) which combines both of this annotations?
#MyAnnotation
private final boolean myField;
How?
Obviously you could create an annotation that provides the equivalent of multiple other annotations.
Equally obviously no JPA provider will support it, since they will check for the javax.persistence annotations only (not that #Type is javax.persistence).
What you want is similar to CDI stereotypes - unfortunately, JPA does not support such a concept, therefore you must copy recurring annotations all over.
If you can afford to wrap your field into an object, you may mark it as #Embeddable and put your field into it - the annotations on that field will be copied wherever you embed that object into an entity. You may extend the annotations using #AnnotationOverrides. Obviously, the drawback of such solution is additional complexity when accessing the field in your entity.

How to use same domain class for HBase and PostgreSQL

I have domain objects that are stored in both HBase and PostgreSQL.
While defining the class the annotations used for PostgreSQL are not applicable to HBase, so I end up defining two classes with the same properties but different annotations. I use Hibernate/Spring framework.
For PostgreSQL, the domain class I use is as below: (snippets)
#Entity
#Table(name="foo_bar")
public class FooBarPgsql implements Serializable {
private static final long serialVersionUID = 5848293352035620189L;
#Id
#Column(name="id")
String id;
#Column(name="name")
String name;
}
for HBase, the class is:
public class FooBarHbase {
String id;
String name;
}
So, If I had to use a single class for both PostgreSQL and HBase, how should I define the class?
I think your combined class is going to be more complicated than two classes with a common interface (which can be dispatched as necessary). The databases are just so different, and HBase is not really compatible with ORM approaches.
I think you will get more bang for your buck with careful use of composition and the like than you will out of trying to fully merge the classes. Since Java can dynamically alter class properties, trying to centralize code in this way is more likely to allow you a clean set of classes for delegating the actual database handling.
You can probably do this if you really really want, but I am not sure it will be worth it in terms of the cost it will certainly take in terms of code quality. Let details depend on interfaces, not the other way around.

Categories

Resources