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.
Related
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.
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;
}
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?
I need to create a database with 2 kinds of 'modules'.
domain focused classes
metadata classes
In the first group it is just simple (or complex rather) RDBMS. The second 'block' are metadata classes which collects information about classes from the first block.
What I have done:
Created Entity class which is parent of all fro 1st part:
#PersistenceAware
#Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public abstract class Entity implements Serializable {
private static final long serialVersionUID = 1L;
}
Created normal schema with all entities inherit somehow Entity class.
Created InternalMapping class as a parent of the whole concept.
#PersistenceCapable
#Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public abstract class InternalMapping implements Serializable {
private static final long serialVersionUID = 1L;
private Entity entity;
//.. cut off getter and setter
}
Created InternalMapping child which should have that feature.
Finally I found it does not work. Probably because Entity does not have any field. But if so I would expect 2 fields: a primary key and class name. In that way I would map every entity by 2 coordinates: ID and class name.
Any idea how to solve that issue? An finally how JDOQL would looks like.
Ps. I know that RDBMS is not the best solution for that kind of problems but people with whom I work wish to have relational database.
Finally I found solution for my problem. I am able to keep entities of different classes keep in one table. Also I am able to do JDOQL request with filtering instances of particular class.
The example is inside GitHub repository here: https://github.com/jgrzebyta/samples-jdo/tree/metalink and within metalink branch. It is slightly modified Tutorial project from datanucleus example.
So.
The lowest level in the inheritance hierarchy is Core interface with the PK defined inside.
Class MyIndex collects different implementations of the Core interface, i.e. Book and Product. Also I have added new column called type for storing Class names only. I am able to retrieve implementations of Core interface and build query filter against type filed because query type core instanceof Book simple does not work. That is the feature of the identity mapping strategy which I have used in my solution: DataNucleus JDO Objects.
PS. If you run command mvn -Pschema-gen compile than you will receive DDL file.
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.