I have a simple base class in which I want to have some common fields, like id etc. The base class is not an Entity by itself.
public class Base {
#Id
protected long id;
protected String someOtherCommonProperty;
}
And I have an entity class, extending the base class.
#Entity
public class Entity extends Base {
String name;
String address;
}
I would expect the entity class to inherit the fields from the base class, but what I get is
[ObjectBox] No #Id property found for 'Entity', add #Id on a not-null long property.
Is there any way to fix that, besides using interfaces and have a lot of duplicated code?
You can use the #BaseEntity annotation.
Have a look at the documentation: Objectbox - Entity Inheritence.
Shameless copy for future reference:
In addition to the #Entity annotation, we introduced a #BaseEntity annotation for base classes, which can be used instead of #Entity.
There three types of base classes, which are defined via annotations:
No annotation: The base class and its properties are not considered for persistence.
#BaseEntity: Properties are considered for persistence in sub classes, but the base class itself cannot be persisted.
#Entity: Properties are considered for persistence in sub classes, and the base class itself is a normally persisted entity.
Example:
// base class:
#BaseEntity
public abstract class Base {
#Id long id;
String baseString;
public Base() {
}
public Base(long id, String baseString) {
this.id = id;
this.baseString = baseString;
}
}
// sub class:
#Entity
public class Sub extends Base {
String subString;
public Sub() {
}
public Sub(long id, String baseString, String subString) {
super(id, baseString);
this.subString = subString;
}
}
Related
I have the following superclass that will be extended by many classes. Its one property, foreignKey, will be the #Id for one of the inheriting classes.
The superclass:
#MappedSuperclass
public abstract Superclass {
#Column(name="FOREIGN_KEY")
private String foreignKey;
// Getters and setters
}
The inheriting class:
#Entity
public class ClassA extends Superclass {
#Id
#Column(name="FOREIGN_KEY")
private String foreignKey;
// Getters and setters
}
When I try building I am given the error:
No identifier specified for ClassA
Is there anyway to accomplish this?
I have an abstract class to represent a type of settings. The inheritance type is in a single table as I wish to be able to access all types of settings irrespective of concrete type. Here is my parent abstract class:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING)
public abstract class Settings extends Model {
#Id
public Long settingId;
public static Model.Finder<Long, Settings> find = new Model.Finder<>(Long.class, Settings.class);
public abstract void run();
}
This is one of my concrete types:
#Entity
#DiscriminatorValue("text")
public class TextSettings extends Settings {
public boolean type;
#OneToOne(cascade = CascadeType.ALL)
public EmailFields emailFields;
public static Finder<Long, TextSettings> find = new Finder<>(Long.class, TextSettings.class);
public static TextSettings get() {
if (find.all().size() > 0)
return find.all().get(0);
else {
TextSettings settings = new TextSettings();
settings.emailFields = new EmailFields();
settings.emailFields.test = "Test"; \\this field is null if you try to get this field with a get on the TextSettings ebean object
settings.save();
return settings;
}
}
}
This concrete type actually contains another ebean model with the OneToOne relationship. Here is the code for that model:
#Entity
#DiscriminatorValue("email")
public class EmailFields extends Model {
#Id
public Long id;
public String test;
public static Finder<Long, EmailFields> find = new Finder<>(Long.class, EmailFields.class);
}
When I try to get the EmailFields model through the TextSettings model, I get the correct id and the object exists in the database, but the field test is null. Any field I add to it is always null.
This type of set up works for me in a non-inheritance ebean model so I can only think it has something to do with the single table. Does anyone know a solution for this, or will I have to copy the test field into the TextSettings model?
Note: I have simplified the code so logically it might not make sense as to why I have one field in EmailFields but the assumption is that I do need it as a separate model as some settings will have this model and some won't. So I don't want boilerplate code in those settings' classes.
Update
So for now I am using the #Embedded and #Embeddable annotations.
#Embeddable
public class EmailFields extends Model
And in TextSettings
#Embedded
public EmailFields emailFields;
This simply copies EmailFields' fields into the TextSettings object and not as a separate entity. Only drawback with this is that it increases the size of the table.
I want to use Hibernate. I have a database schema and I would like to write annotations in my code.
I have az A class. It's look like this:
In A.java:
public class A {
public Integer id;
}
In B.java:
#Entity
#Table(name="table_b")
public class B extends A {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
//How can I get that id attribute from the A class?
#Column
public String string;
}
you put the annotation #MappedSuperClass above class A. The field id has to be annotated in clas A not B.
This is the relevant JPA code:
#MappedSuperClass
public abstract class SuperClass {
#EmbeddedId
private FileId fileId;
protected SuperClass() {
}
public SuperClass(FileId fileId) {
this.fileId = fileId;
}
}
#Embeddable
public class FileId {
protected FileId() {
}
protected File fileName;
public FileId(File fileName) {
this.fileName = fileName;
}
}
#Entity
public MyClass1 extends SuperClass {
#Id
protected String id;
protected MyClass1() {
}
public MyClass1(String id, FileId fileId) {
super(fileId);
this.id = id;
}
}
#Entity
public MyClass2 extends SuperClass {
protected MyClass2() {
}
public MyClass2(FileId fileId) {
super(fileId);
}
}
At runtime I get the following exception:
...
Exception Description: Entity class [class org.abcd.MyClass1] has both an #EmbdeddedId (on attribute [fileId]) and an #Id (on attribute [id]. Both ID types cannot be specified on the same entity.
...
It seems that defining a #EmbeddedId attribute (all attributes of the #Embeddable class) and a #Id attribute together as primary key is not allowed in JPA / Eclipse Link.
Does anybody know a possible solution for this problem?
Any help is appreciated.
Some additional information:
The class MyClassA should contain information (progress, ...; ommited in the code example above) about a certain archive file; the attribute fileId of the super class SuperClass is used to identify this file. Currently fileId (the id-class FileId) only consists of the file name, but later more attributes will be added.
MyClassB contains information about a file IN the archive. This file will be identified with the atttribute id (its the relative path in the archive) and fileId of the super class SuperClass.
I think of the following database structure:
Table "MyClass1":
fileName | id | ...
Table "MyClass2":
fileName | ...
I hope now it's a bit more clear what I exactly want :).
Your mapping doesn't make any sense. You DO have an #EmbeddedId and an #Id in the same class: your MyClassA has na #Id and it extends a SuperClass which already has an #EmbeddedId. I don't know why you would want that? What exactly are you trying to accomplish?
As guys recommended you - maybe changing of the data models will give you more sense here.
And here is my simple proposal :
A Basic class entity containing an ID field and get/set-tters
like :
#MappedSuperclass
public class Entity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
// getters/setters
}
This could be used for basic class for all entities in you model.
Then following your functional requirements maybe next could help you:
#Entity
#Inheritance(strategy = InheritanceType.JOIN)
public class File extends Entity {
#Column(unique=true)
private String fileName;
// other future columns you mention above
}
#Entity
public class ArchiveFile extends File {
// other information here - progress and so on
}
#Entity
public class ArchiveFileTracker extends Entity {
#OneToMany
private ArchiteFile architeFile;
// other specific information here
}
I hope this could covers your requirements.
Good luck,
Simeon
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