I am experiencing NPEs with some embedded JPA metamodel fields using Hibernate 4.3.5.Final.
Specifically, I have the following situation:
#Entity class A
#Embedded class B in class A
#Embedded class C extending class B
I am not getting the 'Unable to locate static metamodel field...' error on startup which seems common in these situations, however all of C_'s fields are null.
Pertinent chunks of my code, simplified for legibility are:
#Entity
#Table(name = "...")
public class A extends AbstractA {
// Attempting to define override in superclass
#AttributeOverride(name = "cField", column = #Column(name = "SOME_FIELD"))
#Embedded
private B b;
...
}
#Embeddable
#Access(AccessType.FIELD)
public class B extends C {
#Column(name="SOMETHING")
private String bField;
...
}
#Embeddable
#Access(AccessType.FIELD)
public abstract class C implements Serializable {
private static final long serialVersionUID = 1L;
private String cField;
...
}
In this example, C_.cField is null.
The corresponding generated metamodel classes for the embedded classes are:
#Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
#StaticMetamodel(B.class)
public abstract class B_ extends C_ {
public static volatile SingularAttribute<B, String> bField;
}
#Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
#StaticMetamodel(B.class)
public abstract class C_ {
// This object is null
public static volatile SingularAttribute<C, String> cField;
}
Unless I've just mucked something up, a key question which I haven't seen answered is - can an embeddable class extend another embeddable class? I've got it working using association rather than inheritance - namely, having C as an an #Embedded field in B - but I'd prefer inheritance if possible.
Related
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;
}
class A implements Serializable{
private static final long serialVersionUID = 1L;
#Id
Integer id;
...
// constructor getter and setter
}
#Entity
class B extends A{
private static final long serialVersionUID = 1L;
#Column
String name;
#Column
String age;
...
//constructors, getters and setters
}
As you see above, class A extends from class B, B should have the identifier id inheritance from A. but i got the No identifier specified for entity: com.d.e.B
what did i missed? thanks in advance.
You missed the #MappedSuperclass annotation on A, to tell Hibernate/JPA that properties and JPA annotations found in A must be considered.
In this example, #MapperSuperclass will work.
If you have entity relationships (one to many, many to one, etc...) the A class should be defined as an entity and the #Inheritance annotation should be used instead.
I had the same error ("No identifier specified for entity") because my A class had the #Inheritance annotation but not the #Entity annotation
I have a problem, I have two entity Job and JobPK
Job class looks like this sample code :
#Entity
#IdClass(JobPK.class)
#Table(name="JOB")
#Inheritance
#DiscriminatorColumn(name="JOB_TYPE")
public abstract class Job implements Serializable {
#Id
#Column(name="FOLDER_ID")
private BigDecimal folderId;
#Id
#ColumnDefinition(position = 1)
private String name;
#Column(name="JOB_TYPE",insertable=false,updatable=false)
private String jobType;
...
}
and JobPk :
public class JobPK implements Serializable {
private static final long serialVersionUID = -3266336718203527905L;
#Column(name="JOB_TYPE",insertable=false,updatable=false)
private String jobType;
#Id
private String name;
#Id
#Column(name="FOLDER_ID")
private BigDecimal folderId;
......
}
I have two class which extends Job : CalculatingJob and ImportingJob
Now I wont to use :
getEntityManager().find(CalculatingJob.class, new JobPK (BigDecimal.valueOf(folderId),name))
and I have problem because I must fill i JobPK descriminator value field. If I don't do that I've got Null Pointer Exception. Descriminator value is in key by default I think but I don't want put information about descriminator value explicite during JobPk creating. I thought that Entity which extends from Job will fill this field automaticaly. Any Idea to bypass this problem, maybe I can get Annotation #DescriminatorVale from CalculatingJob and then put into constructor JobPk
Thanks for Help
Try this configuration for Hierarchy structure
Job.java
#Table(name = "JOB")
#Inheritance
#IdClass(JobPK.class)
#DiscriminatorColumn(name = "JOB_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class Job implements java.io.Serializable {
}
CalculatingJob.java
#Entity
#DiscriminatorValue("CalculatingJob")
public class CalculatingJob extends Job {
}
ImportingJob.java
#Entity
#DiscriminatorValue("ImportingJob")
public class ImportingJob extends Job {
}
JobPK.java
public class JobPK implements Serializable {
}
The discriminator value is entered by hibernate.
I'd like to map lots of subclasses with a common parent class : B extends A, C extends A,... but the database doesn't care A. And B and C have nothing in common (no Id, no reference...).
public class A {
#Id
#Column(name="id")
private Long id;
#Column(name="reference", nullable=false)
private String reference;
}
Is it possible to do this without adding #Entity ?
SOLUTION
#MappedSuperclass
public class A {
#Id
#Column(name="id")
private Long id;
#Column(name="reference", nullable=false)
private String reference;
}
#Entity
#Table(name="B")
public class B extends A {
}
Use #MappedSuperclass on class A:
Designates a class whose mapping information is applied to the entities that inherit from it. A mapped superclass has no separate table defined for it.
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