I have the following situation:
#Entity
class A{
#Id
#SequenceGenerator(name = "SEQ_AID", sequenceName = "SEQ_AID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_AID")
private Long aId;
#OneToOne(fetch=FecthType.LAZY,optional=false,cascade=CascadeType.ALL)
private B b;
...
}
#Entity
class B{
#Id
private A a;
...
}
In other words: There is a OneToOne association between A and B. B is a weak entity, and its Id is derived from class A.
I've already tested some solutions as adding #PrimaryKeyJoinColumn under #OneToOne as this article mentions. But I got this error: "org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): B"
I don't know if it's relevant in this case, but I'm using Oracle 11g.
UPDATED
I think I'm in the right way. Here is the actual state of my problem:
#Entity
class A{
#Id
#SequenceGenerator(name = "SEQ_AID", sequenceName = "SEQ_AID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_AID")
private Long aId;
#OneToOne(fetch=FecthType.LAZY,optional=false,cascade=CascadeType.ALL)
#PrimaryKeyJoinColumn(name="aId")
private B b;
...
}
#Entity
class B{
#Id
#OneToOne
#JoinColumn(name="aId)
private A a;
...
}
The error now is a bit different:
java.sql.SQLException: ORA-00904: "B"."A": invalid identifier
It is trying to find the column A (instead of AID) in the table B. I don't know how to specify that the column name is B.AID and not B.A.
I solved my problem following this link
The correct answer would be:
#Entity
public class A {
#Id
#GeneratedValue
#Column(name = "aId")
private Long id;
#OneToOne(fetch = FetchType.LAZY, optional=false, cascade = CascadeType.ALL, mappedBy = "a")
private B b;
...
}
#Entity
#org.hibernate.annotations.GenericGenerator(name="a-primarykey", strategy="foreign", parameters={#org.hibernate.annotations.Parameter(name="property", value="a")})
public class B {
#Id
#GeneratedValue(generator = "a-primarykey")
#Column(name = "aId")
private Long id;
#OneToOne
#PrimaryKeyJoinColumn
private A a;
...
}
Have you tried this on Entity B?
#Entity class B {
#Id #OneToOne
#JoinColumn(name = "table_a_id") //put the correct column name for A's pk here
private A a;
....
}
Related
I have two model in One to One relation, but when t try to save its provide an ID Error,
#Entity
#Table(name = "app_a_table")
class A {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
#OneToOne(mappedBy = "a", cascade = CascadeType.ALL)
private B b;
...
// Constructor
// Getter & Setter
}
#Entity
#Table(name = "app_b_table")
class B {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
#OneToOne()
#JoinColumn(name = "A_ID", referencedColumnName = "ID")
private A a;
...
// Constructor
// Getter & Setter
}
When I tried to save like below
A newA = new A()
B newB = New B()
newB.setProperties().....
newA.setB(newB);
aRepository.save(newA);
An Exception thrown Column 'A_ID' cannot be null
How I can avoid the conflict
Your mapping is bidirectional, thus you also have to maintain it that way:
A newA = new A()
B newB = New B()
newB.setProperties().....
newA.setB(newB);
// add this:
newB.setA(newA);
aRepository.save(newA);
See code below for my 2 entity classes - when I call the findAll() method from my OrigRepository class, it joins these two tables using both primary keys. I want the join to be between the primary key of the Orig table and the foreign key entry in the MsgResponse table ("OrigID") - any sugggestions?
Orig Entity
#Entity
#Table(name = "originator")
public class Orig {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "OrigID")
private int OrigID;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "OrigID")
private MsgResponse responseInfo;
}
MsgResponse Entity
#Entity
#Table(name = "message_response")
public class MsgResponse {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private int responseId;
#Column(name = "OrigID")
private int OrigId;
#OneToOne(mappedBy="responseInfo")
private Orig OrigInfo;
}
I suggest you to see the jpa documentation
here.
Example 1 should be your case
Try to swap relation ownership, that is:
#Entity
#Table(name = "originator")
public class Orig {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "OrigID")
private int OrigID;
#OneToOne(mappedBy="origInfo")
private MsgResponse responseInfo;
}
#Entity
#Table(name = "message_response")
public class MsgResponse {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private int responseId;
// #Column(name = "OrigID")
// private int origId;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "OrigID")
private Orig origInfo;
}
Note that the #JoinColum annotation is in now in the MsgResponse entity. This is because in a #OneToOne the join column refers to the source entity (see here).
Hope this could help.
I got an object that inherit from another and i am trying to save (persist) it in my db. The problem is that when i try, i got this error :
javax.persistence.PersistenceException:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
I don't know what i did wrong.. Here is my classes :
#Entity
#Table(name = "calamar.derogation")
public class Derogation
{
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "derogation_seq_gen")
#SequenceGenerator(name = "derogation_seq_gen", sequenceName = "calamar.derogation_id_seq",initialValue = 1, allocationSize = 1)
private int id;
#OneToMany(mappedBy="derogation", cascade = CascadeType.ALL, orphanRemoval=true, fetch = FetchType.EAGER)
#OrderBy("id")
private Set<DerogationFille> listDerogationFille;
[...]
}
#Entity
public abstract class DerogationFille{
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
protected int id;
#ManyToOne
protected Derogation derogation;
[...]
}
#Entity
#Table(name = "calamar.derogationlinux")
public class DerogationLinux extends DerogationFille
{
private String chemin;
private String userFam;
private String serveur;
#Column(name="typederogation")
private String type;
[...]
}
I got the error on this lines :
entityManager.getTransaction().begin();
entityManager.persist(derogation);
EDIT 1 ##
I haven't looked at my correctly, i've got this error into it too, i think it is the main problem
ERROR: relation "hibernate_sequence" does not exist
Please annotate your entities like this
#Table(name = "derogation", schema = "calamar")
although true entity naming i get mappedBy reference an unknown target entity property
regarding to this and this the solution for mappedby exception is to naming the entity correctly i did that but i still getting the exception
#Entity
#Table(name = "CONTEST")
public class Contest extends eg.com.etisalat.base.entity.BaseEntity implements
Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "CONTEST_ID_GENERATOR", sequenceName = "SEQ_CONTEST_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CONTEST_ID_GENERATOR")
#Column(name = "ID")
private long contestId;
#OneToMany(cascade = { CascadeType.REMOVE, CascadeType.REFRESH }
,mappedBy="contest")
private List<Challenge> challenges;
//attributes
//getters &setters
}
and this is the ohter entity which has a many to one relation with contest entity
#Id
#SequenceGenerator(name = "CHALLENGE_ID_GENERATOR", sequenceName = "SEQ_Challenge_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CHALLENGE_ID_GENERATOR")
#Column(name = "CHALLENGE_ID")
private long Id;
#ManyToOne(targetEntity=Contest.class)
#JoinColumn(name = "CONTEST_ID")
private Contest conestId;
//attributes
//getters &setters
}
thanks in advance
In Challenge entity, the field should be private Contest contest; with a matching getter and setter - getContest() and setContest().
I'm having problems with generating primary keys with one-to-one relations that use shared primary key.
Here's code:
#Entity
#Table(name = "osoba")
public class Osoba implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "osoba_id")
private Integer osobaId;
#PrimaryKeyJoinColumn
#OneToOne(cascade = CascadeType.PERSIST)
public Pracownik pracownik;
...
and second class:
#Entity
#Table(name = "pracownik")
public class Pracownik
{
#OneToOne
#JoinColumn(name = "osoba_id")
#MapsId("osobaId")
private Osoba osoba;
#Id
#Column(name = "osoba_id")
private Integer osobaId;
...
I've been similar issues and I thought that i've done everything correctly but i still get
org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): entity.Pracownik
when trying to persist Pracownik objects.
You need to follow example from #MapsId documentation (in your case, with #Id instead of #EmbeddedId):
#Entity
#Table(name = "pracownik")
public class Pracownik {
#Id
#Column(name = "oboba_id")
private Integer id;
#OneToOne
#MapsId
private Osoba osoba;
...
}
Inverse side of #OneToOne relationship should be mapped with mappedBy, as usually:
#Entity
#Table(name = "osoba")
public class Osoba implements Serializable {
...
#OneToOne(mappedBy = "osoba", cascade = CascadeType.PERSIST)
public Pracownik pracownik;
...
}
This old question but it works for me. Mayby it will help someone.
SQL Script (Oracle)
DROP TABLE HIBERNATE.PRACOWNIK;
DROP TABLE HIBERNATE.OSOBA;
DROP SEQUENCE HIBERNATE.OSOBA_SEQ;
CREATE TABLE HIBERNATE.OSOBA (
osoba_id NUMBER(15),
CONSTRAINT OSOBA_PK PRIMARY KEY (osoba_id)
);
CREATE TABLE HIBERNATE.PRACOWNIK (
pracownik_id NUMBER(15),
CONSTRAINT PRACOWNIK_PK PRIMARY KEY (pracownik_id),
CONSTRAINT PRACOWNIK_FK FOREIGN KEY (pracownik_id) REFERENCES OSOBA(osoba_id)
);
CREATE SEQUENCE HIBERNATE.OSOBA_SEQ START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
Osoba.java
#Entity
#Table(name = "osoba")
public #Data class Osoba {
#Id
#Column(name = "osoba_id")
#GeneratedValue(generator="osoba-generator", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name="osoba-generator", allocationSize = 1, sequenceName = "OSOBA_SEQ")
private Long osobaId;
#OneToOne(fetch=EAGER, mappedBy="osoba", cascade=ALL)
private Pracownik pracownik;
}
Pracownik.java
#Entity
#Table(name="pracownik")
public #Data class Pracownik {
#Id
#Column(name = "pracownik_id")
#GeneratedValue(generator="pracownik-generator")
#GenericGenerator(name="pracownik-generator", strategy="foreign", parameters=
#Parameter(name = "property", value = "osoba")
)
private Long pracownikId;
#OneToOne(fetch=FetchType.EAGER)
#PrimaryKeyJoinColumn
private Osoba osoba;
}
#Data is Lombok