We have a table in the database which has the following structure:
referenceId - int foreign key to various tables
tableReference - String defining the table
Is this good design, and is it somehow possible to map this relation?
This is very few information to advise you any solution, but JPA Joined Inheritance works something like that:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="PROJ_TYPE")
#Table(name="PROJECT")
public abstract class Project {
#Id
private long id;
...
}
#Entity
#DiscriminatorValue("L")
#Table(name="LARGEPROJECT")
public class LargeProject extends Project {
private BigDecimal budget;
}
#Entity
#DiscriminatorValue("S")
#Table(name="SMALLPROJECT")
public class SmallProject extends Project {
}
This will manage three tables in DB where the main table PROJECT which contain a column PROJ_TYPE to identify the target table.
Related
I'm trying to map one specific many to many table on my database as an entity in JPA (cause I have some specific attributes on my relationship table and I wanted to retrieve this as the class attributes two). But having issues while declaring the IDs.
#Data
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Entity
#Table(name = "user_plan")
public class UserPlan implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#OneToOne
private User user;
#Id
#OneToOne
private Plan plan;
private Integer billingDay;
#Enumerated(EnumType.STRING)
private BillingType billingType;
#Enumerated(EnumType.STRING)
private PlanStatus planStatus;
}
The application starts successfully but when I try to map some repository to manage this table, Hibernate throws an error:
java.lang.IllegalArgumentException: This class [class com.demo.domain.model.UserPlan] does not define an IdClass
How can I use the JPA entity annotation to manage this relationship table? Is it possible?
I cannot simply declare one property in the user class of Plan model and mark it as #ManyToMany, cause the plan table does not have the property that I need to execute some operations, which are declared on UserPlan class, also I cannot move these properties to Plan class, cause the Plan table is just a template of a plan, and the UserPlan have all the specific data (billingDay, billingType and planStatus).
JPA supports relationship tables as a Java class? Or it can be mapped only as a property?
Thanks
You are using multiple #Id annotations. To do so you need to create PrimaryKey class:
public class PrimaryKey implements Serializable {
private User user;
private Plan plan;
// Getter and Setter
}
And you need to add #IdClass(PrimaryKey.class) annotation to your entity class.
If you have a Repository don't forget to change id type to PrimaryKey:
public interface YourRepository
extends SomeRepositoryInterface<UserPlan, PrimaryKey> {
//...
}
Also check this question
My main table has a composite primary key where one of the fields is a sequence. It has a one to one relationship to two other tables where the composite key is the primary/foreign keys of those respective tables. In my java code, I have a PK class which contains a #SequenceGenerator. Since the columns are shared between the tables, I tried having my entities all use the same PK class. However, since my PK class has a field that has a #SequenceGenerator, whenever I try to insert into the foreign key tables, hibernate is generating an additional sequence and is failing on the insert due to the parent key not being found.
Since the #SequenceGenerator was generating an additional sequence for subsequent inserts into the other tables, I cloned my PK class for each other table and removed the #SequenceGenerator so the columns were the same and hibernate wouldn't generate a new sequence during insert. This however created another issue where hibernate is expecting a different PK class than the one that is being provided.
public class AddrEntityPK implements Serializable {
#Id
private long addrTyId;
#SequenceGenerator(name = "ADDR_SEQ", sequenceName = "ADDR_SEQ", allocationSize = 1)
#GeneratedValue(generator = "ADDR_SEQ")
private long addrSeqNum;
}
public class PhoneEntityPK implements Serializable {
#Id
private long addrTyId;
#Id
private long addrSeqNum;
}
public class ElecrMailEntityPK implements Serializable {
#Id
private long addrTyId;
#Id
private long addrSeqNum;
}
#Entity
#IdClass(AddrEntityPK.class)
public class AddrEntity {}
#Entity
#IdClass(PhoneEntityPK.class)
public class PhoneEntity {}
#Entity
#IdClass(ElecrMailEntityPK.class)
public class ElecrMailEntity {}
Since the column names are the same I would expect hibernate to not generate an exception but it instead throws org.hibernate.TypeMismatchException: Provide id of the wrong type for class AddrEntity. Expected AddrEntityPK, got class PhoneEntityPK
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
I have models/Entities as follow:
#Entity
#DiscriminatorColumn(name="type")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Insurance extends Generic<Insurance> {
#OneToOne public myInsurance.models.liability.hivAndVHProtection.Hiv_Answer hivAndVHProtectionAnswer;
}
#MappedSuperclass
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Answer extends Generic<Answer> {}
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorValue("A")
public class Hiv_Answer extends Answer {
#OneToOne public HivAndVHProtection_Variant variant;
}
#Entity
#Inheritance
#DiscriminatorValue("E")
public class Hiv_AnswerForEntities extends Hiv_Answer {
public int proffesionGroup;
public int personCount;
public int contributionPerPerson;
#Transient public int totalContribution;
}
I would like to have in db two tables:
Insurance and Hiv_Answer
I would like that Entities: Hiv_Answer and Hiv_AnswerForEntities be persisted in table Hiv_Answer (share common ID pool)
I would like to have in table Insurance relation to table Hiv_Answer f.e. in column Hiv_Answer_id
I've tried a lot of combination with annotation. None worked like it supose.
Current configuration for me seems to be OK, but it isn't. I am getting extra table: Hiv_AnswerForEntities, and I don't have relation to Hiv_Answer table at all.
It seems that instead use strategy=InheritanceType.SINGLE_TABLE from Hiv_Answer Entity it use strategy=InheritanceType.TABLE_PER_CLASS from superclass Answer
I can't find my mistake.
Please help me solve this.
In JPA you can't redefine your inheritance strategy down the inheritance tree, the root definition of the inheritance sets it for the whole inheritance tree
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