I am developing online web shop, and I need help with Hibernate mapping. I have the following inheritance:
BaseProduct
/ \
Guitar Drum
/ \ / \
AcGuitar ElGuitar AcDrum ElectricDrum
What I want:
1)Common fields such as id, name, description will be in #MappedSuperclass BaseProduct.
2)Musical instrument types (Guitar, Drum) will have common fields for these types of instruments.
3)At the end, concrete classes AvGuitar, ElGuitar etc will have unique properties for this concrete instruments.
The most problem is that I want that there will be two tables for two types of instruments: t_guitar and t_drum (InheritanceType.TABLE_PER_CLASS), and for concrete classes one table InheritanceType.SINGLE_TABLE, which means there will be one table for acoustic and electric guitar and one table for acoustic and electric drums with corresponding discriminant column.
How can I achieve that? Thanks!
Update 1
As I need to interact with the whole hierarchy as one general type and map products to another entities, I did the following:
#MappedSuperclass
public abstract class BaseProduct { //supercclass
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
private String title;
// etc
}
And medium class Product:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Product extends BaseProduct {
}
So, with this solutions any mixes unfortunately still don't work.
You can do it something like...
#MappedSuperclass
public class base {
#Id
private String id; //yr field
}
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(
name="classname",
discriminatorType=DiscriminatorType.STRING
)
public class drum extends base{
String drumProperties; //yr drum prop.
}
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(
name="classname",
discriminatorType=DiscriminatorType.STRING
)
public class guitar extends base {
private String guitarProperties; //guitar prop.
}
#Entity
public class AcGuitar extends guitar{
String acGuitarprop;
}
#Entity
public class ElGuitar extends guitar{
String elGuitarprop;
}
#Entity
public class ElDrum extends drum{
String elDrumprop;
}
#Entity
public class AcDrum extends drum{
String acDrumprop;
}
on result u ll get two table in yr DB ,i. e. guitar and drum
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class base {
#Id
private String id; //yr field
}
now there ll be three table in yr db .for your reference check out. here
Related
I want to apply aggregation function grouping by the DiscriminatorColumn in JPQL.
For example, I want to calculate the sum of calories for each of "grain", "vegetable", ...., which are subclasses of "food" (the code snippet is given below).
I can calculate that by native sql, i.e.SELECT food_type, SUM(calorie) FROM food GROUP BY food_type;. But for inter-database compatibility I want to write it in JPQL.
Do you have any suggestions? Thanks!
#Entity
#Inheritance
#DiscriminatorColumn(name = "FOOD_TYPE")
#Table
public abstract class Food {
#Id
Long foodId;
#Column
String name;
#Column
Double calorie;
}
#Entity
#DiscriminatorValue("GRAIN")
public class Grain extends Food {
// some fields
}
#Entity
#DiscriminatorValue("VEGETABLE")
public class Vegetable extends Food {
// some fields
}
Im my SQL Server Database I have 8 tables with the same structure.
Now I want to insert in selected tables with one Java class.
#Entity
#Table(name = "tbl_Prognosen") //here I want to put all table-Names
public class AZBNachricht { ...
is this possible?
It isn't possible to accomplish what you described.
The closest to code reuse at the entity class level would be to use a #MappedSuperclass class where you place all the shared column names, etc and then extend that for each table implementation with differing table names.
#MappedSuperclass
public abstract class AbstractStructure {
#Id
#GeneratedValue;
private Integer id;
private String column1;
private String column2;
}
#Entity
#Table(name = "table1")
public class Entity1 extends AbstractStructure {
}
// ... so on
For reasons that were around before I got to this project, there are tables that are similar types but have different ID columns.
So, when I try this
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Element implements Serializable {
public String title;
}
#Entity
public class PrimaryElement extends Element {
#Id
long pid;
}
#Entity
public class OtherElement extends Element {
#Id
long oid;
}
But then I get an obvious error
No identifier specified for entity: Element
Now, I can't very well put the ID in the Element class because they are obviously mapped to different columns.
I have tried various flavors of #Id and 'abstract' and #MappedSuperClass and so on..
I am at a complete loss. Is there a way around this?
Any insights would be appreciated.
Thanks!
You can either replace the #Entity and #Inheritance annotations of your Element class by #MappedSuperclass (this annotation is responsible for technical mappings and only PrimaryElement and OtherElement will be fully featured entities) or move the oid field with it's #Id annotation to the class Element and use the #AttributeOverride annotation in it's subclasses to modify the column names (in this case also the abstract class Element will be a fully featured entity).
#AttributeOverride(name="oid", column=#Column(name="primary_element_id"))
UPDATE:
#MappedSuperclass
public abstract class Element implements Serializable {
#Id
private long id;
public String title;
}
#Entity
#AttributeOverride(name="id", column=#Column(name="pid"))
public class PrimaryElement extends Element {
}
#Entity
#AttributeOverride(name="id", column=#Column(name="oid"))
public class OtherElement extends Element {
}
I have two hibernate classes: a base class, and an extended class that has additional fields. (These fields are mapped by other tables.)
For example, I have:
#Entity
#Table(name="Book")
public class A {
private String ID;
private String Name;
// ...
}
#Entity
#Table(name="Book")
public class B extends A {
public String node_ID;
// ...
}
public class Node {
public String ID; // maps to B.node_ID
// ...
}
How do I map this in Hibernate? The hibernate documentation states three types of inheritence configurations: one table per class, one table with a type column, and a join table -- none of which apply here.
The reason I need to do this is because class A is from generic framework that's reused over multiple projects, and class B (and Node) are extensions specific to one project -- they won't be used again. In the future, I may have perhaps a class C with a house_ID or some other field.
Edit: If I try the above pseudo-code configuration (two entities mapped to the same table) I get an error that the DTYPE column doesn't exist. The HQL has a "where DTYPE="A" appended.
This is possible by mapping the #DiscriminatorColumn and #DiscriminatorValue to the same values for both classes; this can be from any column you use that has the same data regardless of which type (not sure if it works with null values).
The classes should look like so:
#Entity
#Table(name="Book")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="published")
#DiscriminatorValue(value="true")
public class A {
private String ID;
private String Name;
// ...
}
#Entity
#Table(name="Book")
#DiscriminatorValue(value="true")
public class B extends A {
public String node_ID;
// ...
}
For anyone who got here like me and does not want to have the dtype column but instead want to use the same table for more than one entity as is I would recommend using this
Basically you can create a Base like this
#MappedSuperclass
public abstract class BaseBook<T extends BaseBook> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
... any other variables, getters + setters
}
#Entity
#Table(name= "book")
public class BookA extends BaseBook<BookA>{
//Default class no need to specify any variables or getters/setters
}
#Entity
#Table(name= "book")
public class BookB extends BaseBook<BookB>{
#Column(name = "other_field")
private String otherFieldInTableButNotMapedInBase
... Any other fields, getter/setter
}
From the above we have created base super class which does not have any entity or table mapping. We then create BookA to be default with the Entity + Table mapping. From there we can create other Entities all extending from BaseBook but pointing to one table
I have 4 persistent classes which all have the same fields (exactly) the only 3 difference between them is 1) the class name, 2) the table name and 3) the data. i am aware that this might seem strange to some but trust me there is a good reason which i won't go into here.
now, i'm using hibernate annotations to configure my class which should work like so:
#Entity
#Table(name = "store")
public class Store
{
#Id
#Column(name = "unique_id")
protected String id;
#Column
protected String category;
...
}
.. and this does work, for a single stand-alone class, however there are many fields to map and i'd like to do it all in one hit for all four similar classes, ie:
public class StoreBase
{
#Id
#Column(name = "unique_id")
protected String id;
#Column
protected String category;
...
}
#Entity
#Table(name = "store1")
public class Store1 extends StoreBase
{}
#Entity
#Table(name = "store2")
public class Store2 extends StoreBase
{}
#Entity
#Table(name = "store3")
public class Store3 extends StoreBase
{}
#Entity
#Table(name = "store4")
public class Store4 extends StoreBase
{}
however when attempting this i get the following exception:
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: package.entities.Store1
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:672)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:546)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:291)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1292)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
i'm guessing this is because the super class is not being searched for the identifier?
is there a way to utilise inheritance in this context?
thanks, paul.
#MappedSuperclass
public class StoreBase
See docs for more info.
Have a look at #MappedSuperclass.