JPA tables inheritance and object mapping - java

Is it possible to map a baseTable with a base class and tell to JPA tool to not insert in the class the fileds that are in the baseTable?
I have the field creation-date which i want in every table of my db, so i created a baseTable with that field and the other tables extend this baseTable.
When i generate the classe for mapping this structure, japtool creates for me each table with creation-date field, which clearly i'd want just in baseEntity class and not in every child class.
There is a way to accomplish it?

If I understood your answer correctly, I think you are looking for JPA Inheritance
#MappedSuperclass
public class BaseEntity {
#Id
protected Integer id;
protected Date createdDate;
...
}
#Entity
public class EntityA extends BaseEntity {
protected String otherAttribs;
...
}
#Entity
public class EntityB extends BaseEntity {
protected Float differentAttribs ;
...
}

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)

Saving same entity in different tables(same schema) using Jpa

I've using spring data JPA repositories to save the data into my tables.
In one of the situation, I've to store data in two different tables. These two tables have the exact same schema. But I can only store in one table as JpaRepository maps to just one table.
Example:
#Entity
#Table(name="users")
class User {
private Long userId;
private String firstName;
private String lastName;
}
interface MyRepo1 extends JpaRepositories<User,Long> {
}
interface MyRepo2 extends JpaRepositories<User,Long> {
}
Is there a way to map a single entity into multiple JpaRepositories? So, when I call MyRepo1.save(user) it saves in Users table and when I call MyRepo2.save(user), it saves in BackupUsers(exact same schema as Users) table.
Thanks
You should have two different entities, for instance, User entity AppUser entity, each one of them pointing to the different tables like this, assuming that the two table names are users and app_users:
#Entity
#Table(name="users")
public class User extends SuperUser {...}
and
#Entity
#Table(name="app_users")
public class AppUser extends SuperClass {...}
Of course, to avoid code duplication you can put your table fields in a superclass named SuperClass, for example:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class SuperUser {
#Id
private Long userId;
private String firstName;
private String lastName;
// getters and setters, constructors
}
After, you need to create two repositories for each entity class:
public interface UserRepository extends JpaRepositories<User, Long> {
}
public interface AppUserRepository extends JpaRepositories<AppUser,Long> {
}
NOTE: To finish, it's not recommended at all to have two tables that hold the same fields.
I don't think you can save in different tables with two different repositories, because you can't specify the table name in repository, but in the entity, I would suggest to use :
// class which hold common fields
class User {
private Long userId;
private String firstName;
private String lastName;
}
// entity for table 1
#Entity
#Table(name="table1")
class User1 extends User {}
// entity for table 1
#Entity
#Table(name="table2")
class User2 extends User {}
// repo for entity 1
interface MyRepo1 extends JpaRepositories<User1,Long> {}
// repo for entity 2
interface MyRepo2 extends JpaRepositories<User2 ,Long> {}

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

Hibernate + JPA can't map different id for sub-class

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 {
}

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