In C# we are using an ORM that lets us specify in each child/Sub Class where we want to store it:
[MapInheritance(MapInheritanceType.ParentTable)] //this means that store employee specific fields in person table
public partial class Employee: Person
{}
I want to use the same in Java side,But in Hibernate we specify strategy in parent Class .We have following structure: enter image description here
I don't want a table for base class.I'd like to store person & employee in user table. and customer in its own table.
But it seems that hibernate has shortcoming in this regard and asks for one hierarchy policy for all branch. I want to be able to change policy in lower branches.
How is it possible to implement this in jpa or hibernate?
You can do that using #MappedSuperclass
One #MappedSuperclass or multiple #MappedSuperclass are allowed in same inheritance hierarchy.
#MappedSuperclass
public class FirstMapped {
#Id int id;
}
#MappedSuperclass
public class SecondMapped extends FirstMapped {
String createdOn;
}
#Entity
public class MyTable extends SecondMapped {
String myColumn;
}
These classes must create just one table: MyTable with columns:
id
createdOn
myColumn
Related
Let's suppose we have the following tables:
USER (user_id)
USER_OWNER (own_id, user_id, type, emp_id, std_id)
EMPLOYEE (emp_id)
STUDENT (std_id)
So, we have a user owner that can be either an employee or a student. We have table USER_OWNER that has FK to EMPLOYEE and STUDENT to provide data integrity.
As I found out neither JPA nor Hibernate supports interfaces. So, what is the best way to solve this problem without inheritance in Hibernate (I can't use inheritance as I need a generic solution for different classes that are not inherited, for example, car, book, table etc)? How to make these relations?
As I understand
#Entity
class User {
private ?UserOwner? owner;
}
#Entity
class Employee {
....
}
#Entity
class Student {
...
}
But what about UserOwner?
I have 2 tables S and I on the database (with a 1:1 relationship), they both have the same id as pk and the hibernate classes I've created are like these:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class S {
#Id
#Column(name = "id")
#GeneratedValue(...)
#SequenceGenerator...
private long id;
....
}
#Entity
#PrimaryKeyJoinColumn(name = "id")
public class I extends S {
....
}
Because of historical reasons, in the database there are objects of type S but not the associated objects of type I. I want to create those I type objects using hibernate. How can I do that? Can I create an I type object from an left join HQL query like this?
select i from I i right join i.id s where s.id = :id
If I try to create a new I entity (new I()) and then persist it, I only managed to get some exceptions as it tries to create an already existing S record. I can't do a simple read/load for I entity as I record does not exist yet. How can I do to create this missing I part entity?
PS I will adjust the question if you point me the unclear things
One approach that will certainly work for you (while is isn't clean one) is to create I records with SQL inserts directly: insert into I_table values (...).
When there are corresponding records in I_table, ORM will start load your objects with I type.
If you have to stay with your ORM and you can delete S records then you can
Load S by id
Delete S (flush? based on your flush mode)
Create I
Copy S values into I
Save I
What you're trying to create is an entity hierarchy. So have to map the entities correctly. The following is probably what you need:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(discriminatorType = DiscriminatorType.CHAR)
#DiscriminatorValue("S")
public class S {
#Id
//........
private long id;
....
}
#Entity
#DiscriminatorValue("I")
public class I extends S {
....
}
With this setting the table S will contain a column named DTYPE (for discriminator type) which identifies whether a row belongs to S or I; this is the default; if you don't want that you have to give a name for the DiscriminatorColumn annotation.
Create an instance of S and save
Create an instance of 'I' by populating the inherited properties (i.e., the properties of S) and its own properties, and save.
When you create a query targeting I, you'll get only instances of I, but if your query targets the S, you'll get instances of both entities.
I was trying to find an answer but, unfortunately, with no luck.
The data structure looks like this:
TABLE_X - contains userId, also userType telling if this is external or internal user
INTERNAL_USERS - contains key userId
EXTERNAL_USERS - also contains key userId
TABLE_X.userId is either INTERNAL_USERS.userId or EXTERNAL_USERS.userId.
Now, I would like to map an entity out of TABLE_X and have user object mapped to correct entity, either INTERNAL_USERS or EXTERNAL_USERS.
How should I do this?
Should I create two fields and map one to INTERNAL_USERS and one two EXTERNAL_USERS and just see which one is not empty?
If I understand correctly your question, what you have to do is to replicate structure of the TABLE_X columns with fields on the TABLE_X class, and add to fields one for INTERNAL_USERS.userID and one for EXTERNAL_USERS.userID
But if you store on TABLE_X.userType if a user is internal or external, I think that the best thing you can do is not create any other table, because you just have the information you need on your first table (TABLE_X). If you want to know all the users that are internal for instance, just do a SQL and select all the values from TABLE_X where userType = "Internal"
Use Hibernate inheritance. Check out the Table per class inheritance pattern. Here you have both INTERNAL_USERS or EXTERNAL_USERS data in TABLE_X with userType as the discriminator column.
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1191
Given the table structure, you can use JPA Inheritance as detailed here:
https://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Example_joined_inheritance_annotations
In Hibernate you can model such relationships as follows. When querying for a User you can then rely on Hibernate to return an instance of the correct type.
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
public class User{
#Id
private Long userId;
}
#Entity
public class InternalUser extends User{
}
#Entity
public class ExternalUser extends User{
}
As noted in the article linked to, Hibernate does not require a discriminator column to be specified when using joined inheritance. It does however support a discriminator column if one is available. As you have one available in your schema - userType - then you could explicitly specify it if you wish. I imagine this would yield some performance benefit in terms of the generated SQL:
Mappings with optional discriminator column:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="userType")
public class User{
#Id
private Long userId;
}
#Entity
#DiscriminatorValue("INT")
public class InternalUser extends User{
}
#Entity
#DiscriminatorValue("EXT")
public class ExternalUser extends User{
}
I am working on a Maven Java web project based on Spring, JPA and Hibernate.
One part of this project shall be reused in another very similar project and gets therefore extracted as Maven module. This service and the corresponding entity are annotated like this:
#Service
public class MessageService
#Entity
public class Message
Both projects have similar but slightly different UserEntities.
#Entity
public class TypeAUser
#Entity
public class TypeBUser
The Message Entity has #OneToMany relationship to one of the UserEntities in each project.
I thought about a generic UserEntity but want to avoid creating additional tables as well as tables with fields of the "other" project.
Any ideas are appreciated.
Best regards,
Stefan
If you don't want to create additional tables, then you might want to consider using SINGLE_TABLE strategy.
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class UserEntity {
...
}
#Entity
public class TypeAUser extends UserEntity {
...
}
#Entity
public class TypeBUser extends UserEntity {
...
}
Well, when talking about Inheritance in Hibernate, you have three options:
Table per concrete class with unions
Table per class hierarchy(Single Table Strategy)
Table per subclass
Since you want to achieve it with one table, I suggest using option 2.
You need just a User table, with a USER_TYPE column to discriminate the user types ( Can be a number, varchar2, etc)
Then you need to create a class User with the following annotations:
You can specify a DiscriminatorColumn if you want, otherwise Hibernate will default to '{className}_TYPE
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="USER_TYPE", discriminatorType=DiscriminatorType.STRING)
public class User { .... }
In your concrete class implementations you can specify a Discriminator value (or if you don't, hibernate will default it to the class name ('TypeAUser'/ 'TypeBUser')
#Entity
#DiscriminatorValue('A')
public class TypeAUser
#Entity
#DiscriminatorValue('B')
public class TypeBUser
I'm using spring CrudRepository throughout my application.
Now I want to also create one for an #Entity that does not have an #Id. Is that possible at all?
//probably ID is always required?
public interface Repository<T, ID extends Serializable>
JPA requires that every entity has an ID. So no, entity w/o an ID is not allowed.
Every JPA entity must have a primary key.
from JPA spec
You may want to read more about how JPA handles a case when there's no id on the DB side from here (see 'No Primary Key').
Alternatively you can extend AbstractPersistable<Long> for your all POJO entities.
Follow example: - https://github.com/spring-projects/spring-data-examples/blob/master/jpa/example/src/main/java/example/springdata/jpa/simple/User.java
Use #IdClass (composite key)
Yes, this is possible. This approach can be used when you read from a DB view. The below example demonstrates how to mark all (2, in the given example) columns as the composite ID:
import java.io.Serializable;
import lombok.Data; // auto-generates AllArgs contractor, getters/setters, equals, and hashcode
#Data
#Entity
#IdClass(MyEntity.class) // <--this is the extra annotation to add
#Table(name = "my_table")
public class MyEntity implements Serializable{ // <--this is the extra interface to add
#Id // annotate each column with #Id
private String column1;
#Id // annotate each column with #Id
private String column2;
}
The above MyEntity uses the full record state as the key:
--so, in addition to #EqualsAndHashcode, do flag the class with Serializable interface;
--annotate each field with #ID
In your <T, ID> repository say the ID is your full (entity) class:
interface MyEntityRepo extends CrudRepository<MyEntity, MyEntity> {
// ^^^the full record is the ID
See also:
docs.oracle.com - Example 7.4-7.5: Non-Embedded Composite Primary Key
baeldung.com/jpa-composite-primary-keys, for more fine-grained custom IdClass, with fewer (than all) columns in the ID.