Imagine that we have :
public class Person {...}
public class Employee extends Person {....}
We make of Employee an entity that have an other table as Person.
With JPA we make our interface extends JpaRepository.
I ask the personRepo.findAll()
Is it possible to get only the List of Person without the Employees?
(I'm analysing this atm so I don't have concreet example, just need to know if this is possible)
Thx in advance
I did the same thing.
This is my code:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#Audited
public abstract class AbstractUser{..}
#Entity
#Audited
public class Admin extends AbstractUser{ .. }
#Entity
#Audited
public class OtherUser extends AbstractUser{ .. }
And then, I use Repository too.
So if I use yoursRepository.findAll(); I get all Users..
In your case, with personRepo.findAll(), you get all person.. You get all those that extend person and those that do not extend it.
EDIT: after question edit
If you want get only employee you can use two different repository, one for Employee and one for Person. So when you use employeeRepository, you get only employee..
Related
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
I am experimenting with Springboot, I have several entities with several properties that are very similar, example: The entity "Car" has model and price properties so do the "Motorcycle" model. I would like to use a a class to define just those common attributes, class "Vehicle" with the properties model and price.
In another words:
Car Motorcicle Vehicle
price price price
model model model
year year
color color
fuel_type fuel_type
... 30 more properites ...30 more properties
I want to use vehicle to map the search result of a SQL union between Car and Motorcycle tables.
public interface ImovelRepositorio extends JpaRepository<Vehicle, Long> {
#Query(value = "here select query with union between car and motorcycle", nativeQuery = true)
List<Vehicle> searchVehicle();
}
Here Vehicle class is a normal class without any annotation. I am getting errors saying that Vehicle is not managed type. Of course my repository doesn't make sense, I expected this error. But how can I achieve what I want?
When I perform a union I am not getting a list of models and am getting a list of one or more models. I want to create a class to "combine" the result of a search.
You can use #MappedSuperClass where the Vehicle can be the mapped super class. The remaining classes can just extend it. Somewhat like below:
The super class:
#MappedSuperClass
class Vehicle {
// constructor, getters, setters
}
The entity classes:
#Entity
class Car extends Vehicle {
// constructor, getters, setters
}
#Entity
class MotorCicle extends Vehicle {
// constructor, getters, setters
}
FluentJPA has a solution for this case.
I see that you use SpringData JPA. In JPQL you can implement this by writing select new fully.qualified.name.of.your.Class(field1, field2) from Entity etc. You have to have proper constructor in your class fully.qualified.name.of.your.Class. This class does NOT have to be an #Entity - it can be any usual POJO or anything else you want.
However, I see that you also use native query. For native query this will not work - you'll have to declare return type as List<Object[]> and do mapping from that yourself, or use #NamedNativeQuery with #SqlResultSetMapping. But do you really need a native query there?
if this question was aksed here, i surely couldnt find it, or it didnt particulary help me.
i've read some tutorials and some questions for Inheritance Mapping, which couldnt quitely solve my questions.
Say i have an abstract class :
User
And 3 more other subclasses :
UserA, UserB, UserC
those all extend User.
Every Subclass has its own table, Superclass User, meanwhile, doesn't.
In my other class Website i have a ArrayList, or should i say Collections, of Users.
The list should fetch all users of the Website.
Which strategy should i use ? I thought of MappedSuperclass, but since in my Website class the List is of User type, so am not sure what to do here.
Thanks for any help!
With JPA the Java implementation always depends on you own preferences and requirements, sometimes it is the matter of a choice.
Yes, #MappedSuperclass will do.
You can have every child with unidirectional relationship to Website. Then you gonna have Website object inside your User class (with a bunch of annotations), which will map to a database as foreign_key field (presume you are using SQL storage and 'Repositories' DAO abstraction from JPA).
It is not necessary to store a collection of users inside Website class. Just think if you really need it - it can be a mess to support consistency.
But there are cases where you need bidirectional relationship. When you store objects in memory (for caching purposes for example) you'll probably need to have this collection. In this case why not to have 'User' collection? You will fetch data through dedicated repositories(or even if you're not using those, any other way will be using 'User' tables with foreign_key, not the 'Website' table) anyway.
So, for example with the use of Spring Data JPA you can define a unidirectional relationship in a superclass and use 'repositories' next way(and bidirectional example you can find anywhere in the internet, so I am not providing it):
#Entity
public class SuperUser extends User {
...
}
#Entity
public class BasicUser extends User {
...
}
#MappedSuperclass
public abstract class User implements Serializable {
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "website_uuid", nullable = false)
protected Website website;
...
}
#Entity
public class Website implements Serializable {
...
}
#Repository
public interface SuperUserRepository extends CrudRepository<SuperUser, Long> {
Iterable<SuperUser> findByWebsite(Website website);
}
#Repository
public interface BasicUserRepository extends CrudRepository<BasicUser, Long> {
Iterable<BasicUser> findByWebsite(Website website);
}
What you are asking for seems a typical "Table-per-concrete-class" inheritance strategy. https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#entity-inheritance-table-per-class
In older version of the user guide, it has mentioned that separate table will be mapped for each non-abstract classes. In the latest document the "non-abstract" part is not mentioned but I believe it still works similarly.
So it looks something like:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
abstract class User {...}
#Entity
class UserA extends User {...}
#Entity
class UserB extends User {...}
#Entity
class UserC extends User {...}
But you should be aware of this inheritance strategy usually gives inefficient query as internally it is using union.
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 have a scenario where I have a entity hierarchy structure implemented in hibernate.
It is InheritanceType.JOINED
Parent class:
#Entity
#Table(name = "LOY")
#Inheritance(strategy=InheritanceType.JOINED)
public class Loy implements Serializable
Child class boundary
#Entity
#Table(name = "LOY_BOUNDARY")
#PrimaryKeyJoinColumn(name="ID")
public class LoyBoundary implements Serializable
Child class percentage
#Entity
#Table(name = "LOY_PERCENTAGE")
#PrimaryKeyJoinColumn(name="ID")
public class LoyPercentage implements Serializable
I have a Customer entity class which is linked to the Loy entity class in a #ManyToOne.
The Customer can only be linked to one Loy at a time.
What I want to achieve is that I want to query the Customer class with unique id (passport number) and then get The Loy for the specific Customer through the #ManyToOne mapping in the Customer entity.
The problem that I'm sitting with is that I do not know which subclass of Loy is linked to the Customer.
I can go instanceOf to get the specific subclass but I want to try and avoid it.
I can also add a visitor pattern in the subclass entity, but not sure if this is best practice.
I would go with a visitor. Using instanceof won't work if the ManyToOne is lazy-loaded, because the actual type of the Loy won't be any of your subclasses, but a Hibernate proxy extending the Loy class. Indeed, Hibernate has no way to know, from the ID of the loy in the customer, which kind of Loy it refers to.
And a visitor is more OO and cleaner anyway.