Inheritance Hibernate/JPA multiple levels - java

I have problems with defining a schema with multiple level inheritance,
so in my case I have a schema like bellow :
Model(id,created)
UserModel extends Model (login,password)
CustomerModel extends UserModel (orders)
StoreOwnerModel extends UserModel (stores)
ProductModel extends Model(name,price)
I have set inheritance strategy in Model on TABLE_PER_CLASS, so that means that I want for each sub class of Model create a table.
and the inheritance strategy in UserModel is set to SINGLE_TABLE to have just one table for all UserModel's subClasses.
But in my data base I see that for each UserModel subclasses a table is generated.
and I can't find the DiscriminatorColumn user_type in the generated table table USERS corresponding to UserModel.
here are my entities:
Model.class
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
#MappedSuperclass
public abstract class Model {
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
private Integer id;
#DateTimeFormat(pattern="dd/MM/yyyy hh:mm:ss")
private Date created;
//getters/setters
}
UserModel.class
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="user_type",discriminatorType=DiscriminatorType.STRING)
#SecondaryTable(name="USERS")
#DiscriminatorValue("user")
public class UserModel extends Model{
#Column(unique=true)
private String login;
//getters & setters
}
CustomerModel.class
#Entity
#DiscriminatorValue(value="customer")
public class CustomerModel extends UserModel{
private List<OrderModel> orders;
//getters & setters
}
StoreOwnerModel.class
#Entity
#DiscriminatorValue(value="store_owner")
public class StoreOwnerModel extends UserModel{
private List<StoreModel> stores;
//getters & setters
}
ProductModel.class
#Entity
public class StoreOwnerModel extends UserModel{
private String name;
private double price;
//getters & setters
}
PS: this is not a duplucated Question, I dont Find this Answer on any of previous ones.

according to #chris I should remove #Inheritance from Model entity
and I also removed #SecondaryTable(name="USERS") from UserModel and it worked just perfectly.

Related

Hibernate: How to map a class that "has-a" subclass to a single table?

I have a class BacktestResult that contains a property BacktestInputs. I want hibernate to create a single table that contains the contents of both. Here's what I have so far:
#Entity
#Table(name="backtest_result")
public class BacktestResult {
#Id
Long backtest_id;
public int userId;
BacktestInputs inputs;
#OneToMany
#OrderColumn(name="backtest_id")
public BacktestChartDataPoint[] series;
//getters and setters
The BacktestChartDataPoint class looks like this:
#Entity
#Table(name="backtestchart_datapoint")
public class BacktestChartDataPoint {
#Id
public Long id;
public Long backtest_id;
#ManyToOne
#JoinColumn(name="backtest_id", nullable=false, insertable=false, updatable=false)
private BacktestResult backtestResult;
The BacktestInputs class looks like this:
public class BacktestInputs {
public String strategy_name;
public String version;
etc...
As long as I comment out the BacktestInputs in BacktestResult, hibernate correctly creates 3 tables:
backtest_result
backtest_result_series
backtestchart_datapoint
But I want the contents of BacktestInputs to be included in the BacktestResult table. If I uncomment it, get error:
Could not determine type for:
net.tekknow.moneymachine.model.BacktestInputs, at table:
backtest_result, for columns: [org.hibernate.mapping.Column(inputs)]
What is the proper way to handle class hierarchy with "has-a" relationships, NOT "is-a" relationships?
You need to annotate the class BacktestInputs with #Embeddable
(see https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#embeddables)

How to query jpa entity in JOINED inheritance, without creating table for same?

I am trying to implemet inheritance hierarchy as mentioned in below image using hibernate Joined strategy.
Since Joined strategy creates table for entity regardless of entity class is Concrete or Abstract.
I don't want to create separate table for "CompanyEmployee" so I declared it as mapped superclass, but I should able to query this class/subclasses in polymorphic way.
Since it is mapped superclass I can't do this, and if I declare it to be entity it will create table which I want to avoid.
So, is there any way I can achieve this? I am thinking about mixed inheritance but from below quote it doesn't seems to be a good solution.
Mixed Inheritance
We should begin this section by saying that the practice of mixing inheritance types within a single
inheritance hierarchy is currently outside the specification. We are including it because it is both useful
and interesting, but we are offering a warning that it might not be portable to rely on such behavior,
even if your vendor supports it.
Inheritance hierarchy
#Entity
#Table(name="j_employee")
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="emp_type", discriminatorType=DiscriminatorType.STRING)
public abstract class JEmployee extends AuditLog implements Serializable {
#Id
#Basic
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="employee_id")
private Integer employeeId;
#Basic
#Temporal(TemporalType.DATE)
#Column(name="join_date")
private Date joinDate;
#OneToOne
#JoinColumn(name="person_id", nullable=false)
private Person person;
#Column(name="emp_type", updatable=false, insertable=false)
private String empType;
//Getters and Setters
}
#Entity
#Table(name="j_contract_employee")
#DiscriminatorValue(value="JContractEmployee")
#PrimaryKeyJoinColumn(name="contract_employee_id", referencedColumnName="employee_id")
public class JContractEmployee extends JEmployee implements Serializable {
#Basic
#Column(name="daily_rate")
private Integer dailyRate;
#Basic
#Column(name="term")
private Integer term;
//Getters and Setters
}
//Don't want to create table for this class, but I should able to query this clas/subclasses in polymorphic way
#MappedSuperclass
public abstract class JCompanyEmployee extends JEmployee implements Serializable {
#Basic
#Column(name="vacation")
private Integer vacation;
//Getters and Setters
public Integer getVacation() {
return vacation;
}
public void setVacation(Integer vacation) {
this.vacation = vacation;
}
}
#Entity
#Table(name="j_part_time_employee")
#Access(AccessType.FIELD)
#DiscriminatorValue(value="JPartTimeEmployee")
#PrimaryKeyJoinColumn(name="part_time_employee_id", referencedColumnName="employee_id")
public class JPartTimeEmployee extends JCompanyEmployee implements Serializable {
#Basic
#Column(name="hourly_rate")
private Integer hourlyRate;
//Getters and Setters
}
#Entity
#Table(name="j_full_time_employee")
#Access(AccessType.FIELD)
#DiscriminatorValue(value="JFullTimeEmployee")
public class JFullTimeEmployee extends JCompanyEmployee implements Serializable {
#Basic
#Column(name="salary")
private Integer salary;
#Basic
#Column(name="penion")
private Integer pension;
//Getters and Setter
}

more name attributes in Table

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

JPA Entity Mapping Inheritance

I have problem with JPA Entity Mappings. I have some classes:
ClassA
#Entity
public class ClassA {
private int id;
#OneToMany
private List<ClassB> listClassB;
}
ClassB
#Entity
public class ClassB {
private int id;
#ManyToOne
private ClassA classA;
#OneToMany
private List<ClassC> listClassC;
}
ClassC
#Entity
public class ClassC {
private int id;
#ManyToOne
private ClassB classB;
private String code;
private String name;
#OneToMany
private List<ClassD> listClassD;
}
ClassD
#Entity
public class ClassD {
private int id;
private Long value;
private Date startDate;
private Date finishDate;
#ManyToOne
private ClassC classC;
}
Now, I want to have another entity that have all the property and association of ClassC, and have it's own property (the value is numbers of ClassD that related to Class C). When I use class inheritance like this:
ClassE
#Entity
public Class ClassE extends ClassC {
// All ClassC properties
private Long numberOfClassD;
}
It throw com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'pegawai0_.DTYPE' in 'field list'.
"Maybe" caused by missing Discriminator column. But in my case, I don't have discriminator column.
* How to solved this issue ?*
Can I still use Class Inheritance? Or another way to solve this?
Thanks.
In the example, both ClassC & ClassE have been marked with #Entity and hence the 'Table per class hierarchy' inheritance strategy is used. By default, the discriminator column name is 'DTYPE'.
You can just try it out with using 'Table per class' hierarchy strategy on 'ClassC'. The tables generated, however, would be much different from the 'Table per class hierarchy' though.
You might want to check which inheritance strategy you would need based on the domain model. This link would be good guide to that:
http://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch10.html
Like Alan Hay suggest in the comment, the ClassC and ClassE doesn't have any relationship in database. So, using #MappedSuperclass solve the problem.
I implement it this way:
#MappedSuperclass
public Class SuperClass {
private int id;
#ManyToOne
private ClassB classB;
private String code;
private String name;
#OneToMany
private List<ClassD> listClassD;
}
#Entity
#Table(name = "table_name")
public Class ClassC extends SuperClass {
// No Property
}
#Entity
#Table(name = "table_name")
public Class ClassE extends SupperClass {
private String classECustomValue;
}

Mapping Multiple Classes to a Table in Hibernate, Without a DTYPE Column

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

Categories