I want to achieve something like this:
#Entity
#Table(name = "beer")
public class Beer {
#Id Long id;
String brand;
String name;
}
#Entity
public class BeerWithIngredients extends Beer {
#OneToMany(mappedBy="beer")
List<BeerIngredient> ingredients;
}
#Entity
public class BeerIngredient {
#Id Long id;
// .. whatever fields
#ManyToOne
#JoinColumn(name = "beer_id")
BeerWithIngredient beer;
}
Physically, all beer data is in one table, but I want to split it into more entities.
Please note that:
I would not like to use discriminator column in the database
There isn't a column that I could use for #DiscriminatorFormula
I do not want to embed Beer inside BeerWithIngredients, because it essentially is not a composition, but proper inheritance
Is there a way of achieving this with JPA (Hibernate)? Right now it complains about missing discriminator column, that I don't plan to provide.
Introduce a new super class RootBeer with all common beer properties. Annotate this class with MappedSuperClass. Make Beer and BeerWithIngredients inherit from RootBeer and annotate them with Entity as well as Table(name="beer").
For an example check this.
Related
I have an entity that corresponds to some table in DB
#Entity
#Table
public class MyEntity {
#Id
private Long id;
#Column
private String description;
#OneToMany
private List<Foo> foos;
...
//getters setters
...
}
And I would like to extend that entity for read-only and have additional joins to another table. I need this joins only in one case for specific read user-case:
#Entity
public class ExtendedEntity extends MyEntity {
#ManyToMany(fetch = FetchType.EAGER)
private List<Bar> bars;
}
Just using extensions will create a discriminator column in DB, which I don't need since I'm using the ExtendedEntity only for the read. I found I hack with using #DiscriminatorFormula that will be resolved to the same Integer value like this:
#DiscriminatorFormula("0")
#DiscriminatorValue("0")
public class MyEntity
#DiscriminatorValue("00")
public class ExtendedEntity extends MyEntity
But this really looks like a hack. With using #MappedSuperclass I cannot have associations, but this is the main reason I need to extend my entity.
What other options do I have and what are the best practices for this use-case?
I have couple of entities, Person and PersonSnapshot. PersonSnapshot is same as Person, except for, it has its own primary key.
I would like use Java class hierarchy so that I need not redefine property names, but I am not able to get them to work as the two tables will have different "#Id" properties.
#Entity
#Table(name = "Person")
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
class Person {
#Id
private int id;
#name
private String name;
}
I need to store its snapshot as in
#Entity
#Table(name = "Person_Snapshot")
class PersonSnapshot extends Person {
#Id
private int snapShotId;
}
I don't want to create an abstract MappedSuperClass for common attributes as I will end up with 3 classes. Is there any way achieve the same result with just these two classes ?
Move everything that is common between the two classes into a superclass and annotate it with #MappedSuperclass. For more details see for example this: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html
EDIT: For those who may pass through here in the future, I'd like to share something I found. Although it's not going to work for this particular situation, hibernate does have an #Where annotation. With this annotation you could have N amount of Sets. Each set would have #Where(clause='column=value'). I will not be using the #Where solution but it may work out for you.
I'm new(ish) to JPA Hibernate and am looking for some help. I don't necessarily know what to search for either so here is a quick example of my problem.
I need to take a Set and split it into multiple Set dependent on a value of a field.
Lets look at something simple:
public class Customer{
private String name;
private String age;
private Set<Order> orders;
}
public class Order{
private int amount;
private String status;
}
Goal: I would like to have Hibernate split my Customer's orders by their status into seperate Sets. Currently I use the #POSTLOAD annotation to loop over the Set and seperate them out accordinly. I would prefer Hibernate do it for me resulting in something like:
public class Customer{
//Irrelevant stuff from above...
private Set<Order> pendingOrders;
private Set<Order> completedOrders;
private Set<Order> canceledOrders;
}
These sets would be based off the order's status.
pendingOrders is where Order.getStatus() == "PENDING"
completedOrders is where Order.getStatus() == "COMPLETED"
canceledOrders is where Order.getStatus() == "CANCELED"
The tables are directly represented by the classes and are both considered "Entities". (Customer and Order)
If I haven't provided adequate information, could you please point me to a proper search for what I am "trying" to accomplish. In terms of JPA terminology I have no idea what to search for and could really use some help!
Thank you!
The best approach in your case is create a discriminator column and some extra classes to use it. Example
#Entity
#Table(name = "ORDER")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "STATUS", discriminatorType = DiscriminatorType.STRING)
public abstract class Order{
}
#Entity
#DiscriminatorValue(value = "PENDING")
public class PendingOrder extends Customer {
}
public class Customer{
//Irrelevant stuff from above...
private Set<PendingOrder> pendingOrders;
//same fo0r all others types
}
And if you notice the orders have some specific information only valid for pending orders or completed orders, then probably the best approach is use
#Inheritance(strategy = InheritanceType.JOINED)
Or
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
And add the specific columns in those new tables
Writing the case it will be more simple to explain.
I am using Seam 2.3.1 v Hibernate JPA 2.0 and in our project. I have a base Person Entity Class.
#Entity
#Name("person")
#Inheritance(strategy = InheritanceType.JOINED)
#Table(name = "person")
public class Person extends BaseEntity {
private String name;
private String surName;
private String email;
private String phone;
// getter & setters
}
And I have 3 more Entity extends from Person as #Inheritance(strategy = InheritanceType.JOINED): Personel, Musteri, DisPaydas
#Entity
#Name("personel")
public class Personel extends Person {
private String appellation;
// getter & setters
}
I want to List personels, musteris and dispaydas in my bean however when I set them in my Group Entity, I want to save them as Person.
In fact in DB there is no difference between person_id and personel_id, they are same. However when I listing it, they are List<Personel>
In summary:
I want to get List<Person> from List<Personel>
or Person from Personel object.
You're going to have to define an #Id and #Column in the Person class for the person_id.
However, since the column has a different name in the child entity, you'll need to change it using an #AttributeOverride to point to the personel_id #Column.
It couldn't hurt to use a #DiscriminatorColumn in the parent and #DiscriminatorValue in the children, but I don't think Hibernate requires those.
I have 3 classes:
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue
private Long id;
...
}
#Entity
public class Person extends BaseEntity {
private String name;
...
}
#Entity
#AttributeOverride(name = "id", #Column = (name = "idStudent"))
public class Student extends Person {
private float avgGrades;
...
}
I would like to override ID property so in Student table there would be a idStudent column instead of id. Unfortunately, the code above doesn't work. It looks like #AttributeOverride only works for the class you extending (and no one step further). Is there any way to override attribute name in situation I've descried (override attribute in class which exteds our class being extended) ?
Your problem is very easy to understand, if you know what the default inheritance type is: SINGLE_TABLE.
That means all entities that extending Person are in the same table. And thus Person already defines the ID column. Because you would otherwise violate the contract of the primary key column of your Person table.
I cite the JavaDoc of #AttributeOverride as well:
May be applied to an entity that extends a mapped superclass or to an embedded field or property to override a basic mapping or id mapping defined by the mapped superclass or embeddable class (or embeddable class of one of its attributes).
It always helps to read the JavaDoc first, before asking questions here.
What can you do about it? Make your Person a #MappedSuperclass (or create a BasePerson that is one).