Using Hibernate with MySQL, I like to use same class and store in two different table. How can i map one class with multiple tables?
I came across this thread,
hibernate two tables per one entity
which gives a suggestion to use two different Identity Name for same class through XML configuration. Can some one give me pointers how should i do this mapping in Java configuration? Or can it be done using annotation?
example,
There is Student Class
#Entity
#Table(name="Student_1")
public class Student{
#Id
private int StudentId;
private int StudentName;
private int studentMailId;
}
I like to have similar Table with same fields with the table name as Student_2. How should I annotate and use it to save in different tables?
I know this question was asked long time ago, and a response was posted here .
I would like to suggest an alternative way, without using any of hibernate things.
Declare an interface with getter and setter methods of commun columns, then make your Student_1 class and Student_2 classs implement this interface.
Leave your JPA mapping in this two class as usual, then in your code, you can invoke method of this interface instead.
Related
I am trying to divide a monolithic system into microservices using Spring Boot. The problem I encountered is that while each microservice should normally have classes that implement the service functionality, I need to receive and deal with objects that encapsulate many classes that are related to other microservices. For example, the code below is part of microservice1, which provides student information:
class Microservice1{
int id;
String name;
int grade;
Record record;
}
Notice now that the Record object is of a class that belongs to another microservice, which is microservice2, which provide student record as the following:
class Microservice2{
List<int> marks;
Behaviour behaviour;
}
Now behaviour is also another object whose class belongs to another microservice 3, and so on.
My question is: How do I get rid of the issue of having to include all these classes in microservice 1 because microservice1 needs to deal with them while providing the service? The problem is serious because I have many encapsulated classes inside each other, and I would need to include most of the monolithic system classes in one microservice.
As far as i can see, you are making your microservices way too granular. You'll have a lot of trouble implementing that way.
IMHO, if a Record is related to a Student AND belongs to the same business context, they belong to the same microservice.
As David said in the comments, Bounded Contexts concept can (really) help you.
Anyway, imagine that you want to follow in that line which you're proposing. If a Record belongs to Microservice B and you have to reference it by composition somewhere in Microservice A, the only thing you'll need, is it's primary key. Not the whole object.
Would be something like this:
Microservice A:
Student.java
public class Student {
private Integer id;
private String name;
private Integer grade;
private Integer recordId;
// getters and setters omitted for brevity
}
Microservice B:
Record.java
public class Record {
private Integer recordId;
private List<Integer> marks;
private Integer behaviourId;
// getters and setters omitted for brevity
}
And so on..
But as I said, maybe this is not the best approach.
See here a good article on Bounded Context.
I believe you are clear on the bounded context aspect. Practically, it will be hard to review each and every class for having a relationship with each other as you have shown in your sample. I would suggest to use a tool that can visually show you the dependency. Then you after placing them into their bounded context you can begin the key mapping, to fetch data from other microservice(s).
I am trying to design a database schema so that it is applicable for the Hibernate's Table Per Class inheritance strategy. So, I will not let Hibernate to generate the tables, instead I need to design them myself in Liqibase but in such way that Hibernate can use them with that strategy.
My entity classes should look like this.
Vehicle.java
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Vehicle {
#Id #GeneratedValue
private int id;
private String name;
private String brand;
}
Car.java
#Entity
public class Car extends Vehicle {
private String oil;
}
Bike.java
#Entity
public class Bike extends Vehicle {
private String frame;
}
Now, I know that that this strategy means that all the fields are in all tables, but I am not sure about two things.
1) Do I need to include the ID in the derived tables?
2) Do I even need a Vehicle table in the DB, since it will actually never be used as an entity (rather just an abstract class)?
I'd appreciate if someone could clear that for me.
Now, I know that [the table-per-concrete-class] strategy means that all the fields are in
all tables,
Well no, you seem to be confused. With InheritanceType.TABLE_PER_CLASS, each concrete entity class E maps to a table that contains columns corresponding to all the fields of E, including inherited ones, but not including fields of entities that are not superclasses of E.
This is to be contrasted with InheritanceType.SINGLE_TABLE, in which all entity types in a whole inheritance hierarchy map to the same table, which then necessarily contains a column for each property of each entity in the hierarchy (without duplicating inherited fields).
Note also that it is odd that your Vehicle entity contains fields with the same names as fields of its subclasses. Java fields are not polymorphic, so this is unlikely to be what you want. It's certainly unnecessary.
but I am not sure about two things.
1) Do I need to include the ID in the derived tables?
Supposing that you stick with TABLE_PER_CLASS, yes, each entity table needs to provide a column for each persistent property of the corresponding entity class, including those inherited from superclasses. That includes id.
2) Do I even need a Vehicle table in the DB, since it will actually
never be used as an entity (rather just an abstract class)?
Not if you actually declare it abstract, but if you leave it concrete, then yes, you need a table for it. And that makes sense, because in that case you could have Vehicle entities that are neither Cars nor Bikes.
Hibernate schema generation tool should be able to generate your schema if you annotate your entities correctly.
In this case Vehicle table which be generated since your entity class is concrete. You need to define the class as abstract.
All the fields defined in the superclass (including the #Id) will be copied in the corresponding child class tables. There is a limitation though regarding id auto generation. You cannot use the table per class inheritance strategy with the GenerationType.IDENTITY strategy since the generated keys should be unique across all tables. Identity creates unique ids per table
Make sure the Generation.AUTO strategy does not map to the IDENTITY strategy for your RDBMS (You can specify a strategy explicitly eg GenerationType.TABLE to override the default)
I am just starting to apply RealmDB in my application. I have one question regarding nesting objects.
I have previous experience working with Entity Framework. There is one useful feature available in Entity Framework - mappings.
The problem is that I need to have nested object. Here is an example
public class SessionModel extends RealmObject {
private UserModel userModel;
private ExpirationDate expirationDate;
}
As you can see the members are not simple types, but classes instead. Therefore it is problematic to map them correctly.
I wonder if there is any way to use custom retriever or mapper to get collect all objects manually and return a model with all fields set.
Thank you
I have a base (abstract) class A and two subclasses B and C which I want to persist them using table-per-hierarchy approach in Hibernate. Suppose B has 'width' and C has 'height' field which are of the same type. By default Hibernate creates two separate columns but fills only one column for each row. Now, what happens if I map both fields to the same column in DB, say 'length'?
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.INTEGER)
public abstract class A {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer id;
}
#Entity
#DiscriminatorValue("1")
public class B extends A {
#Column(name="length")
public Integer width;
}
#Entity
#DiscriminatorValue("2")
public class C extends A {
#Column(name="length")
public Integer height;
}
I ran some basic tests and no error happened, but I didn't see anything like this in documentations -considering this practice prevents creation of lots of empty columns in a complex application and should be mentioned - and really don't have the expertise to declare this as a safe practice.
Has anyone done something like this? Are there any drawbacks to this approach? Also does the no-NOT-NULL-on-subclasses limitation holds in this scenario?
I have not encountered any problems after using this method for two years in production.
But notice that you cannot set different restrictions on fields because database sees them as one column.
I'm borrowing the "slice" meaning from C++.
Let's say I hava a simple POJO that's persisted via Hibernate:
class Person {
private long id;
private String name;
...
// getters and setters here
...
}
Now, when I retrieve an object from the database I know it was "instrumented" by Hibernate (its real class is a Person-derived generated automatically). I want to convert it back to a "plain" person object. Tnat would be used, for instance, to submit the object to XStream and have the result containing only what Person contains.
I could do it by defining a copy constructor, but I don't want to have the hassle of having to write copy constructors for every ORM class (not to mention the violation of DRY principle).
So I was wondering if
a) is there already a Java lib that does it?
b) If not, would it be practical to write one using reflection?
In case of (b), any recomendations/guidelines/code skeletons would be appreciated.
The bean mapping library Dozer does an excellent job of this and is dead simple to use.
Simply map an instance of the bean returned by Hibernate to it's own class:
Person person = session.load(...);
BeanMapper mapper = ...;
Person cleanPerson = mapper.map(person, Person.class);
voila, no more Hibernate proxies or lazy-loaded collections!
The class org.apache.commons.beanutils.BeanUtilsBean probably does almost everything you want. The copyProperties method will go through calling the getters on your Entity and looking for setters with a matching property name on a target object you provide. You may need to handle some nested entities, depending on what kind of behavior you want and if/how you map relationships.
If you need to get more sophisticated you can register a Converter for turning your nested entity types into something else as well.
There is an interesting discussion about your problem here
http://www.mojavelinux.com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/
Several solutions are proposed in the comments. In particular
http://code.google.com/p/entity-pruner/
http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/
I personally am huge on layer separation, and would argue that classes that you want to serialize across the wire or to XML should actually be separate from your data access layer classes, which would also solve the problem.
class SerializablePerson
{
... fields you care about ...
SerializablePerson(Person person)
{
... set only what you care about ...
}
}
You could have a Person class without persistence information wrapped by a persistent counterpart, like this:
public class Person implements Serializable
{
private String name;
// others.
}
public class PersistentPerson
{
private Long id;
private Person data; //
public Person getPerson() { return this.data; }
}
I'm not sure the design is worth it. The dual model makes me throw up in my mouth a little, just while writing this example.
The larger question is: Why do you think this is necessary? IF there's no good way to tell XStream to not include the id when serializing, I'd say it'd be better to write your own javax.xml.bind.Marshaller and javax.xml.bind.Unmarshaller to get what you want.
There are better ways to solve this problem than bastardizing your entire design.