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.
Related
I decided to use single table inheritance which results in having multiple classes and I can't access the child's fields through a parent object in the view part of the application. So far I didn't find a nice solution how to deal with it in Thymeleaf. What does it mean?
Before I split my classes to use single table inheritance I could easily pass 1 object class that contained all the information needed to create or display the object but it had too many fields that would be null. With multiple classes thymeleaf doesn't really allow you to cast objects to a different type(and from what I understand it wouldn't be a good practice to do that in a view part of the application). So what is really the best way to deal with this problem?
I can come up with ideas like:
Create a DTO that contains the fields from all the classes and transform the objects to this class, it would be great in a create-view (POSTing DTO and then creating an object from it and adding to the database). But if I used this method for displaying information then it would mean casting each of the objects to a DTO class which kind of misses the point of single table inheritance in my opinion. I feel like this is too similar to going back to no inheritance at all.
Passing multiple objects or a parent object + a different object that would hold the rest of the information that the parent class doesn't hold. This also seems kind of weird.
Adding one method to a parent class per sub-class additional field and overwrite them in the sub-classes to return actual values while parent would return null. Not sure if this would fix the problem of creating the objects from a view though.
Let's assume this example with three simple classes where Person is a parent class and Client and Employee are children of it. I will skip getters, setters and constructors for simplicity.
Person main class that holds shared fields
#Entity
#Inheritance
#DiscriminatorColumn(name = "person_type", discriminatorType = DiscriminatorType.STRING)
public abstract class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
int personId;
int age;
String name;
}
Client class that extends person with additional field favouriteProduct
#Entity
#DiscriminatorValue(value= "CLIENT")
public class Client extends Person {
String favouriteProduct;
}
Employee class that extends person with additional fields salary and position.
#Entity
#DiscriminatorValue(value= "EMPLOYEE")
public class Employee extends Person {
String position;
int salary;
}
Given this simple structure I would like to create Employee and Client objects through a single form via a POST request and also display them together in a different view with their fields that are unique to each subclass. Problem is that I would need to pass an object that holds all the fields to the view to actually make it work which comes back to the problem and solutions that I came up with. Is there any correct way or best practice how to deal with this? I thought DTOs should rather scale down from full objects to objects with less fields.
Conclusion: if the answer isn't really that simple then what is really the use of single table inheritance in this case and why isn't it a good idea to just go back to 1 table implementation? I already know about polymorphic queries and it is a nice bonus but so far I can't really deal with the problem I explained above. Thanks in advance!
I don't know about Thymeleaf (sorry!), but I do know about object-oriented programming a bit. Leaving frameworks aside and talking from a pure OO perspective, parent classes know nothing about their children (inheritors). Only the opposite can be true, and that's if you use the appropriate access modifiers. Given that said, I believe you can not do what you want unless there is some ugly framework black magic going under the hood haha.
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;
}
Assume that I have several realm objects (tables) with many connections between them, and I don't yet have all the objects pre populated.
I want to be able to create relationships by their ids (primary keys).
For example, I have JSON file with an object that has a list of another object's ids (not the actual object, although that another object is already exists in the realm db), I want to be able to populate those into objects directly without having to query them first.
How is that possible?
Realm is designed to be an object database without impedance mistach that could happen from mapping Java objects to an entry in table. Relation in Realm is specifically handled to adhere the principle above.
For example, one can describe relationship between object in following.
public class ObjectA extends RealmObject {
...
#PrimaryKey
private long id;
...
}
public class ObjectB extends RealmObject {
...
private RealmList<ObjectA> entries;
...
}
The relation you want, i.e. relation by primarykey id, seems much close to relational databases and it is not supported.
Is it possible to annotate a class as #Embeddable or a property as #Embedded?
Sample code:
#Embeddable
class A{
...
}
class B{
...
}
#Entity
class Foo {
A a;
#Embedded B b;
}
When to prefer #Embedded and #Embeddable?
There are two primary uses for #Embedded/#Embeddable as far as I know:
First, and most important: Splitting up large entity classes. In the database world, a large table (one with many columns) is fine. Breaking up such a table might even make things worse, and be in collision with database design principles. In Java (or object oriented languages in general), on the other hand, a large class is a code smell. Here, we would like to split the classes, including entity classes, into smaller units. #Embedded/#Embeddable allows us to easily do this without having to split the database table.
Second, it allows for reuse of common mappings between entities. Say each table has a simple revision tracking, with two columns containing the username of the person who changed the row, and the time it happened. Then, one can make an #Embeddable entity covering these rows, and then reuse this across all entities by embedding it (rather than repeating the variables corresponding to these columns in each entity.)
If we have Person and Address that are two POJOs, You would not want to create another table for Address but you would want to embed the address within the person table. So Address is adding up value to the Person object but doesn't make any sense individually. In this case we may go with:
#Embeddable
public class Address{
}
#Entity
public class Person
{
#Embedded
private Address address;
}
You would use #Embeddable and #Embedded together. You mark your class as #Embeddable, which indicates that this class will not exist in the DB as a separate table. Now when you use #Embedded on the field itself.
The word embeddable and embedded gives you a big clue actually.
Embeddable = This class can be embedded in a class
Embedded = This class will now be embedded in your class as a field.
I guess if you annotate class as #Embeddable you don't need to annotate field as #Embedded. Also, if you annotate class as #Embeddable and you want to use it as primary key, you can use #Id only, but if it is not annotated as #Embeddable, you have to use #EmbeddedId on field to work as primary key.
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.