I am trying to save data in two table using OneToOne mapping.I have followed
this,this,this,this and few more online resources to accomplish this, but it is throwing
ORA-02291: integrity constraint (TableName.TEST_ID) violated - parent key not found
Creating a table where column TESTID is foreign key. In the parent table TESTID is primary key.That primary key is generated using sequence generator
CREATE TABLE EW_TEST_REFTABLE (
ID int NOT NULL PRIMARY KEY,
TESTNAME VARCHAR2(20) NOT NULL,
TESTID int,
CONSTRAINT test_id FOREIGN KEY(TESTID)
REFERENCES EW_TESTDATA(TESTID)
);
Ew_testdataEntity.java (Entity class of parent table)
#Entity
#Table(name = "EW_TESTDATA")
public class Ew_testdata {
#Id
#SequenceGenerator(name = "sube_seq",
sequenceName = "EW_TESTDATA_SEQ",
allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sube_seq")
#Column(name = "TESTID")
private int testid;
#Column(name = "TESTNAME")
private String testname;
// Ew_test_reftable is another entity class.In that table the column
// TESTID (foreign key) must be same as the primary key of this
// entity/table(EW_TESTDATA)
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "TESTID",unique = true)
private Ew_test_reftable ewtestreftable;
//Constructor
// getter & setter
}
Ew_test_reftable.java
#Entity
#Table(name = "EW_TEST_REFTABLE")
public class Ew_test_reftable {
#Id
#SequenceGenerator(name = "subf_seq", sequenceName = "EW_REF_SEQ", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "subf_seq")
#Column(name = "ID")
private int id;
#Column(name = "TESTNAME")
private String testname;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "TESTID")
private int testid;
//Constructor,getter & setter
}
Service to save data using Jpa
#Override
public Ew_testdata ew_testdata(String name) {
Ew_test_reftable ew_test_reftable = new Ew_test_reftable();
ew_test_reftable.setTestname("test");
Ew_testdata ew_testdata = new Ew_testdata();
ew_testdata.setTestname(name);
ew_testdata.setEwtestreftable(ew_test_reftable);
iew_tEst.ewTestdata(ew_testdata);
return null;
}
The problem seems to be similar to few other problem described in SO but still i am not able to figure out where I am making mistake
Your entity and table structure looks opposite, and that making so much confusion to understand.
Now, referring to exception
ORA-02291: integrity constraint (TableName.TEST_ID) violated - parent key not found
This mean, you don't have reference of parent id in child table when adding new row to child table.
In Ew_test_reftable class, you have
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "TESTID")
private int testid;
If I understand correctly, testid is your foreign key in EW_TEST_REFTABLE, then why are you using GenerationType.IDENTITY ? This will create new sequence id and may not match with parent key and result in error/exception.
As per my understanding of your design,
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "TESTID")
private int testid;
change to
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "TESTID",unique = true)
private Ew_testdata ew_testdata;
And similar to above code should be removed from Ew_testdata entity (There might be slight change here and there)
Related
I've these tables in my Oracle database (which I can't change):
Table_A
Table_B
Table_AB
ID (PK)
ID_B (PK)
ID_A (PK)
COMMON_ID (PK)
COMMON_ID (PK)
B_ID (PK)
...
...
COMMON_ID (PK)
Tables A and B have a many-to-many relationship and Table AB contains two foreign keys:
FK_1: ID_A, COMMON_ID referencing table A (ID, COMMON_ID)
FK_2: B_ID, COMMON_ID referencing table B (ID_B, COMMON_ID)
I tried to map these table but I have a problem in my jointable due the fact column "COMMON_ID" is shared between FK_1 e FK_2. Hibernate in fact tries to create the jointable with two column with the same name, generating this exception:
org.hibernate.MappingException: Repeated column mapping for collection: B.collectionA column: COMMON_ID
These are my entities, please can anyone help me to solve the problem? Thank you in advance!
Entity A:
#Entity
#Table(name = "Table_A")
#IdClass(value = A_PK.class)
public class A implements Serializable {
private static final long serialVersionUID = 2210864155927195752L;
#Id
#SequenceGenerator(name = "TABLE_A_SEQ", sequenceName = "TABLE_A_PKSEQ", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TABLE_A_SEQ")
private long id;
#Id
#Column(name="COMMON_ID")
private Integer commonId;
#ManyToMany
#JoinTable(name = "TABLE_AB",
joinColumns = {
#JoinColumn(name = "ID_A", referencedColumnName = "ID"),
#JoinColumn(name = "COMMON_ID", referencedColumnName = "COMMON_ID")
},
inverseJoinColumns = {
#JoinColumn(name = "B_ID", referencedColumnName = "ID_B"),
#JoinColumn(name = "COMMON_ID", referencedColumnName = "COMMON_ID")
}
)
#LazyCollection(LazyCollectionOption.FALSE)
private List<B> collectionB;
getter, setter, hashcode, equals
Entity A_PK:
public class A_PK implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private Integer commonId;
getter, setter, hashcode, equals
Entity B:
#Entity
#Table(name="TABLE_B")
#IdClass(value = B_PK.class)
public class B implements Serializable {
private static final long serialVersionUID = -5761968943282358603L;
#Id
#Column(name = "ID_B", unique = true, nullable = false)
#SequenceGenerator(name = "TABLE_B_SEQ", sequenceName = "TABLE_B_PKSEQ", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TABLE_B_SEQ")
private Long id;
#Id
#Column(name="COMMON_ID")
private Integer commonId;
#ManyToMany(mappedBy = "collectionB")
private List<A> collectionA;
getter, setter, hashcode, equals
Entity B_PK:
public class B_PK implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Integer commonId;
getter, setter, hashcode, equals
#Entity
#Table(name = "parent");
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Parent {
#Id
#SequenceGenerator(name = "ME_SEQ", sequenceName = "ME_SEQ", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ME_SEQ")
#Column(name = "PARENT_ID", columnDefinition = "NUMBER(38,0)", nullable = false, unique = true)
private Long id;
}
There is also a child entity (seperate table) which has a PK and FK that points to Parent ID.
#Entity
#Table(name = "child")
public class Child extends Parent {
#Id
#Column(name = "PARENT_ID")
private Long id;
}
Even though there is two separated tables, I get an error from Hibernate:
org.hibernate.mapping.UnionSubclass cannot be cast to
org.hibernate.mapping.RootClass
Is it not possible to have ID in the child class, even if it's a different table from the parent?
I have 2 tables in database side(oracle)
create table GROUPS
(
ID NUMBER not null,
GROUP_NAME VARCHAR2(30)
)alter table GROUPS
add constraint ID primary key (ID)
and
create table ITEM_GROUP
(
ITEM_ID VARCHAR2(30) not null,
GROUP_ID NUMBER not null
)
alter table ITEM_GROUP
add constraint ITEM_GROUPD_ID primary key (ITEM_ID, GROUP_ID)
alter table ITEM_GROUP
add constraint ITEM_GROUP_FK01 foreign key (GROUP_ID)
references GROUPS (ID);
Than I have mapping classes in Java side. I want to make thing, when I am selecting group to take all his items too, and I want to save item with hibernate it is all .
#Entity
#Table(name = "GROUPS")
public class Group {
#Id
#Column(name = "ID", nullable = false)
#javax.persistence.SequenceGenerator(name = "groupIdGenerator", sequenceName = "GROUP_SEQ", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "groupIdGenerator")
private int id;
#Column(name = "GROUP_NAME")
private String groupName;
#JsonManagedReference
#OneToMany(fetch = FetchType.EAGER, mappedBy="group",cascade = CascadeType.ALL)
private List<GroupItems> groupItems = new ArrayList<>();
// setters and getters
}
#SuppressWarnings("serial")
#Embeddable
public class GroupItemPK implements Serializable {
#Column(name = "ITEM_ID")
private String merchantId;
#Column(name = "GROUP_ID")
private int id;
// getters , setters , constructors , equals hashcode methods
}
#Entity
#Table(name = "ITEM_GROUP")
public class GroupITEM {
#EmbeddedId
private GroupITEMtPK id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID")
#JsonBackReference
private Group group;
}
I am interested in did i make any mistakes in build relationship ? If I did what is my mistakes , because I can not do my select and save queries without exceptions.
I am trying to do in my Code
List<Group> list = sessionFactory.getCurrentSession().createQuery("from Group a").list();
and here is my Exception
org.hibernate.engine.jdbc.spi.SqlExceptionHelper could not extract ResultSet [n/a]
java.sql.SQLSyntaxErrorException: ORA-00904: "GROUPITE0_"."ID": invalid identifier
I have created Address object which has a ID (AddressPK) which get generated by a sequence. The address object also has a foreign key to Client object via the ID of the client object (ClientPK). The ClientPK also generated via a sequence. However, it complains at the time I try to deploy the ear to web logic server saying that only one generated element can exist for an entity. The class snippets as follows. Anyone can help how to define a foreign key using an object that also uses a sequence generator in addition to the object primary key?
public class Address implements Serializable{
#EmbeddedId
private AddressPK id;
#Embedded
private ClientPK clientId;
...
}
#Embeddable
public class AddressPK implements Serializable {
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="RoidSequenceGenerator")
#SequenceGenerator(name="RoidSequenceGenerator",sequenceName="roid_sequence", allocationSize=1)
#Column(name = "a_roid")
private long value;
...
}
#Embeddable
public class ClientPK implements Serializable {
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="RoidSequenceGenerator")
#SequenceGenerator(name="RoidSequenceGenerator",sequenceName="roid_sequence", allocationSize=1)
#Column(name = "c_roid")
private long value;
...
}
I think you do not understand what is the Primary Key and what the difference from the Foreign Key. Primary key (PK) can be generated for each database entity. And there is a restriction in JPA that generated value must be only one. Foreign Key (FK) in the other hand is a link to the PK of another entity. So you need to create another entity with generated PK and have a link to it with OneToMany, ManyToMany or another kind of association. For example:
#TableGenerator(name = "entities_id_generator", table = "SEQUENCE",
pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue =
"ENTITY_SEQ", initialValue = 0, allocationSize = 1)
public class DBObject1 implements Serializable {
#Id
#GeneratedValue(generator = "entities_id_generator", strategy = GenerationType.TABLE)
private Long id;
#ManyToOne
#JoinColumn(name = "source_id")
private DBObject2 source;
}
#TableGenerator(name = "entities_id_generator", table = "SEQUENCE",
pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue =
"ENTITY_SEQ", initialValue = 0, allocationSize = 1)
public class DBObject2 implements Serializable {
#Id
#GeneratedValue(generator = "entities_id_generator", strategy = GenerationType.TABLE)
private Long id;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "source")
private List<DBObject1> objects;
}
In example above the virtual FK for entity DBObject1 will be stored in column source_id. It is virtual because there will not be any physical FK in database table. But JPA will link these objects if you ask.
Hibernate:
/* load entities.Department */ select
department0_.name as name4_0_,
department0_.id as id4_0_
from
J_DEPT department0_
where
department0_.name=?
Hibernate:
/* load one-to-many entities.Department.employees */ select
employees0_.dept as dept4_1_,
employees0_.id as id1_,
employees0_.id as id5_0_,
employees0_.dept as dept5_0_,
employees0_.name as name5_0_
from
J_EMP employees0_
where
employees0_.dept=?
Note that ID and DEPT columns are selected twice.
#Entity
#Table(name = "J_EMP")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeq")
#SequenceGenerator(name = "mySeq", sequenceName = "CNTRY_SEQ")
private Long id;
private String name;
#ManyToOne
#JoinColumn(name = "dept")
private Department deptNameInEmp;
}
#Entity
#Table(name = "J_DEPT")
public class Department {
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeq")
#SequenceGenerator(name = "mySeq", sequenceName = "CNTRY_SEQ")
private Long id;
#Id
#Column(name = "name")
private String deptNameInDeptEntity;
#OneToMany(mappedBy = "deptNameInEmp")
Set<Employee> employees;
}
UPDATED:
It was done intentionally to put #GeneratedValue on non-PK. However, now I've updated as you specified.
I've copy-pasted the new queries:
Hibernate:
/* load entities.Department */ select
department0_.id as id4_0_,
department0_.name as name4_0_
from
J_DEPT department0_
where
department0_.id=?
Hibernate:
/* load one-to-many entities.Department.employees */ select
employees0_.dept as dept4_1_,
employees0_.id as id1_,
employees0_.id as id5_0_,
employees0_.dept as dept5_0_,
employees0_.name as name5_0_
from
J_EMP employees0_
where
employees0_.dept=?
I guess its still the same.
And here are the tables:
CREATE TABLE "XYZ"."J_DEPT"
( "ID" NUMBER(*,0) NOT NULL ENABLE,
"NAME" VARCHAR2(255 BYTE) NOT NULL ENABLE,
CONSTRAINT "J_DEPT_PK" PRIMARY KEY ("ID")
)
CREATE TABLE "XYZ"."J_EMP"
( "ID" NUMBER NOT NULL ENABLE,
"NAME" VARCHAR2(255 BYTE),
"DEPT" NUMBER NOT NULL ENABLE,
CONSTRAINT "J_EMP_PK" PRIMARY KEY ("ID"))
here is the code -i'm pasting here as it is :
#Entity
#Table(name = "J_DEPT")
public class Department {
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeq")
#SequenceGenerator(name = "mySeq", sequenceName = "CNTRY_SEQ")
#Id
private Long id;
#Column(name = "name")
private String deptNameInDeptEntity;
#OneToMany(mappedBy = "deptNameInEmp")
Set<Employee> employees;
public Set<Employee> getEmployees() {
return employees;
}
}
#Entity
#Table(name = "J_EMP")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeq")
#SequenceGenerator(name = "mySeq", sequenceName = "CNTRY_SEQ")
private Long id;
private String name;
#ManyToOne
#JoinColumn(name = "dept")
private Department deptNameInEmp;
public Employee() {
}
And here is the test case:
#RunWith(SpringJUnit4ClassRunner.class)
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
#ContextConfiguration(locations = { "classpath:test-applicationContext.xml" })
#Transactional
public class EmpTest {
#Autowired
private SessionFactory sessionFactory;
#Test
public void testDept() {
final Department find = (Department) sessionFactory.getCurrentSession()
.get(Department.class, Long.parseLong("1"));
System.out.println("find res = " + find);
}
}
Probably because of this part:
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeq")
#SequenceGenerator(name = "mySeq", sequenceName = "CNTRY_SEQ")
private Long id;
#Id
#Column(name = "name")
private String deptNameInDeptEntity;
There is something wrong here, the GeneratedValue cannot be applied to a non PK. Did you mean:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeq")
#SequenceGenerator(name = "mySeq", sequenceName = "CNTRY_SEQ")
private Long id;
#Column(name = "name")
private String deptNameInDeptEntity;
If not, and if this was intentional, please explain your goal and show your table(s).
Update: I can't reproduce the problem. I copy pasted the code you provided and here is the query I get:
select
employee37x0_.id as id135_,
employee37x0_.dept as dept135_,
employee37x0_.name as name135_
from
J_EMP employee37x0_
where
employee37x0_.id=?
Works as expected.
A Google search on "hibernate duplicate aliases" reveals some (old) issues so I don't exclude anything but I couldn't find any proof of recent existing problems. Can you provide a test case (using an embedded database)?