Hibernate #Embedded and #Embeddable - java

I have to create a simple database using Hibernate, but whatever i did, i got this error:
org.hibernate.MappingException: Repeated column in mapping for entity: tr.com.ozer.datastructures.GameObject column: x (should be mapped with insert="false" update="false")
Firstly i am using PostgreSQL 11, and Hibernate 5.4
Here is what i am trying to do:
#Embeddable
public class Position {
private Integer x;
private Integer y;
// Setters end getters
}
#Entity
public class GameObject {
#Id
private Integer id;
#Embedded
private Position absPosition;
#Embedded
private Position relativeToBaseA;
#Embedded
private Position relativeToBaseB;
// Setters and getters
}
I do not want to use #AttributeOverrride since my Position class have more fields then here and i dont want to define all of them for every field. Instead i would just write seperate fields.
And I dont care database column names so much atm. Are there any auto-naming mechanisim in Hibernate? Like absPosition_x, absPosition_y, relativeToBaseA_x, relativeToBaseA_y etc.
Note: Despite that i have the "implicit_naming_strategy" conf in my hibernate.cfg.xml, i still get the error. Here is the line:
<property name="hibernate.implicit_naming_strategy">org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl</property>

Ok, the error is on my part. But i will post my solution in case anyone has it.
I have been using Hibernate 5 and initializing it with the old method.
After i initialized with StandardServiceRegistry, the error perished.
It is actually interesting, the old way initializing metod works normal without #Embedded annotations on version 5.4. It should give "wrong way initialition error" or something and i wouldnt have spend hours on this one!

Related

jpa - Multiple #ElementCollection in two different #Embeddable classes

I have an entity with two Embedded classes of the same type and which one has an ElementCollection of the same type two. The business logic is apparently correct, but I am experiencing some problems with lack of knowledge in JPA, I guess.
Let's check my classes:
#Entity
public class Etapa extends EntidadeBase {
#Embedded
private CronogramaDeDesembolso cronogramaDeReceita;
#Embedded
private CronogramaDeDesembolso cronogramaDeDespesa;
}
#Embeddable
public class CronogramaDeDesembolso {
#ElementCollection
private List<Parcela> parcelas;
}
I am receiving the following error log.
Caused by: org.hibernate.HibernateException: Found shared references
to a collection:
nexxus.convenioestadual.dominio.planodetrabalho.etapa.Etapa.cronogramaDeReceita.parcelas
Do you guys have any clue of what is wrong and how can I fix it?
EDIT:
Due comments I did this edit and it do not worked too
#Entity
public class Etapa extends EntidadeBase {
#Embedded
#AttributeOverride(name = "parcelas", column = #Column(name = "parcelasReceita"))
private CronogramaDeDesembolso cronogramaDeReceita;
#Embedded
#AttributeOverride(name = "parcelas", column = #Column(name = "parcelasDespesa"))
private CronogramaDeDesembolso cronogramaDeDespesa;
}
Is there any reason why you have decided to use this structure ? Typically when converting an object to an RDBMS you would need to model the relationships. When you use an embeddable it will add the column (or columns) associated with it to the table. So when you do this normally (not collections) it is fine.
When you do a collection it runs into issues. Mainly there is no way to represent a collection in a single row (since this is an entity you could have many of them so effectively for each object you only have one row) & one column. So when you represent a collection you actually have to have a second table with a column referencing it back to the first. It's really the opposite thinking of a normal object. The collection entries need to know what collection they were associated with instead of the collection being knowledgeable of its entries.
So in some POJO you could have and these....
MyListObject {
//Some implementation of things you want to collect
}
MyClass {
List<MyListObject> myListObject;
}
But to model this in JPA you would need to have these represented by two tables.
Your object that will be in the list.
#Entity
MyListObject {
#ManyToOne
#JoinColumn(name = "MY_CLASS_KEY")
private MyClass myClass;
}
Your object/entity that will have the list.
#Entity
MyClass {
#Id
#Column(name = "MY_CLASS_KEY")
private Long myClassKey;
#OneToMany(mappedBy = "myClass")
private List<MyListObject> myString;
}
I hope this helps.
A quick search on Google turned up this in StackOverflow:
JPA Multiple Embedded fields
It would seem as though you have to do some explicit annotation overriding over the fields within the embeddable class. There are some code examples in the linked answer as well that should give you a good idea of where to go.
Cheers,

Hibernate Inheritance.JOINED generated FK name

I am currently trying to use inheritance within Hibernate and came across InheritanceType.JOINED. I like the idea of concentrating all data in one table and sharing IDs rather than having duplicate columns in all the sub type tables (#MappedSuperClass). But Hibernate automatically generates indexes on my sub class tables on the id column like FK_idx3wiwdm8yp2qkkddi726n8o everytime I initialize my Hibernate singleton. I noticed that by hitting the 64 key limit on my MySQL Table as the names are generated differently on every startup.
What is the proper way to handle this? Can this be fixed by annotations? What else could I try?
I know that there are countless similar Questions on SO but haven't been able to identify one solving my specific problem.
I am not going to disable hbm2ddl.auto during dev mode.
I am using MyISAM. There are no actual Foreign Keys. This is why Hibernate generates default indexes, I think. Anyway, the problem would be identical with InnoDB and real Foreign Keys as the names would still be quite random. Or maybe Hibernate would actually check for existence in this case. I don't really see, why it does not do this on MyISAM tables.
As I hit similar problems before, the solution could also be to specify a name for that single-column index. But how?
Super Class: FolderItem
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class FolderItem implements Comparable<FolderItem>
{
#Id
#GeneratedValue
protected int id;
protected String name;
#OneToOne
#ForeignKey(name = "fkParent")
protected Folder parent;
...
}
Sub Class: Folder
#Entity
public class Folder extends FolderItem
{
#OneToMany(mappedBy = "parent")
#OrderBy(value = "sortOrder")
private List<FolderItem> children;
...
}
What I tried
add #Index to FolderItem.id - this created an index on the FolderItem table as one would expect, but didn't affect the Folder table
copy protected int id; to Folder and tried to add an #Index to it, which resulted in an Exception similar to "duplicate definition of ID"
add #Table(appliesTo = "Folder", indexes = { #Index(name = "fkId", columnNames = { "id" }) }) to Folder class, which actually created my specified index as expected, but still created it's own FK_9xcia6idnwqdi9xx8ytea40h3 which is identical to mine, except for the name
Try #PrimaryKeyJoinColumn(name = "foler_item_id") annotation for Folder class.

Persisting third-party classes with no ID's

Say I have the following Java class, which is owned by a vendor so I can't change it:
public class Entry {
private String user;
private String city;
// ...
// About 10 other fields
// ...
// Getters, setters, etc.
}
I would like to persist it to a table, using JPA 2.0 (OpenJPA implementation). I cannot annotate this class (as it is not mine), so I'm using orm.xml to do that.
I'm creating a table containing a column per field, plus another column called ID. Then, I'm creating a sequence for it.
My question is: is it at all possible to tell JPA that the ID that I would like to use for this entity doesn't even exist as a member attribute in the Entry class? How do I go about creating a JPA entity that will allow me to persist instances of this class?
EDIT
I am aware of the strategy of extending the class and adding an ID property it. However, I'm looking for a solution that doesn't involve extending this class, because I need this solution to also be applicable for the case when it's not only one class that I have to persist, but a collection of interlinked classes - none of which has any ID property. In such a scenario, extending doesn't work out.
Eventually, I ended up doing the following:
public class EntryWrapper {
#Id
private long id;
#Embedded
private Entry entry;
}
So, I am indeed wrapping the entity but differently from the way that had been suggested. As the Entry class is vendor-provided, I did all its ORM work in an orm.xml file. When persisting, I persist EntryWrapper.
I don't have much experience with JPA, but I wouldn't extend your base classes, instead I would wrap them:
public class PersistMe<T> {
#Id
private long id;
private T objToWrap;
public(T objToWrap) {
this.objToWrap = objToWrap;
}
}
I can't test it, if it doesn't work let me know so I can delete the answer.

Custom wrapper for id key

I want to wrap id in custom class. Like this
#Entity
#Table(name = "USERS")
public class User {
#EmbeddedId
UserId id;
}
#Embeddable
public class UserId implements Serializable {
private Long value;
}
The issue in auto generation value for UserId. What I should do to make #GeneratedValue on value be workable?
BTW, It would be great if id would be initialized automatically itself.
As far as I know Hibernate only generates values for a field marked as the #Id. I found this post and Hardy's answer supports this.
We have tried to do similar and managed it via a pre-insert listener. It was fairly complex and non-ideal though. Also you might find different behaviour on different database palatforms. Using Oracle sequences would mean that you need to assign the value pre-insert (Hibernate does a select to get the value and then an insert) but with MySQL the auto incrementing field would assign the value and hibernate does an insert to generate the auto generated value and then select to find out what the value was.

Hibernate not JPA compliant regarding #Access?

According to my JPA 2.0 book (and online documentation), I should be able to mix field and property access within a single entity or entity hierarchy. The annotation of #Access on the class specifies the default access. When placed on a field or property getter #Access can specify that the default should be overridden for this field.
#Entity
#Access(AccessType.FIELD)
Class Foo {
#Id
int id;
#Column(name = "myfield")
String myField;
#Column(name = "myProp")
#Access(AccessType.PROPERTY)
public int getMyProp () {
return 3;
}
public void setMyProp (int p) {
// do nothing
}
}
This class should result in a table with three columns. However it doesn't with Hibernate...the "myProp" column is missing from the table because apparently Hibernate takes its field vs property cue from the entity ID and runs with it...totally ignoring the JPA spec with regards to #Access.
Can anyone confirm this or did I make a stupid mistake somewhere?
I've seen similar (not the same but similar) issues like HHH-5004 so I wouldn't exclude that this might be a new one (the TCK doesn't seem exhaustive). But what version of Hibernate are you using? Did you try with the latest?
Based on the docs your code seems to be right. The #Access(AccessType.FIELD) annotation on top is unnecessary, because you annotated the field int id;
This tells hibernate to use field access. I tried a very similar example with annotations and xml config mixed. This leads to the same behaviour, so it's probably a bug in hibernate.
I tried with hibernate 3.5.3

Categories

Resources