[Hibernate-JIRA] Created: (HHH-2679) One to Many Unidirectional Association using Join Tables and <list> causes duplicate key constraint violation when an entry is deleted from the list.
by Priyajeet Hora (JIRA)
One to Many Unidirectional Association using Join Tables and <list> causes duplicate key constraint violation when an entry is deleted from the list.
-----------------------------------------------------------------------------------------------------------------------------------------------------
Key: HHH-2679
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2679
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.2
Environment: Java 1.5, Hibernate 3.2, MySQL 5. Might also effect NHibernate similarly.
Reporter: Priyajeet Hora
Priority: Critical
Consider this unidirectional one-to-many relation done using join tables.
Person --> Address (*).
The hibernate mapping is pretty much the same as
http://www.hibernate.org/hib_docs/v3/reference/en/html/associations.html#...
Though I am using <list> rather than a <set>
Following is the DDL (presented roughly) created by the hbm2ddl tool.
Table PersonAddress
Person_id varcahr not null
Address_id varchar not null unique
Person_list_index integer not null
primary key (Person_id, Person_list_index)
I create a person1 - person_id=1.
I create add1, add2, add3 - address_id=2,3,4 respectively.
then I add all 3 addresses to the list in person1.
persist it to database.
all good.
At this point in the database --
person_id---person_list_index---address_id
1--0--2
1--1--3
1--2--4
I get person1 back.
I remove add1.
save person1 back.
CONSTRIANT VIOLATION HERE DUE TO DUPLICATE KEY.
looking at what hibernate does ...
So after 1st save and before remove this is whats in the database -
person_id---person_list_index---address_id
1--0--2
1--1--3
1--2--4
basically shows the one to many there.
I want to remove the record no. 1--0--2. That is the 1st one.
So with the 1st row gone, hibernate needs to shift other records up so that the new list index is assingned.
expected output----
1--0--3
1--1--4
This is how hibernate proceeds
Step1: save info and delete on 1--2--4, to get rid of that last record.
Step2: update 1--0--2 to 1--0--3
BANG...CONSTRAINT VIOLATION DUE TO DUPLICATE KEY.
Why? because "3" in that address_id column is already there and that column is "unique" according to DDL.
Step3: update 1--0--3 to info saved from step1, that is to 1--1--4.
But cant persist this since step 2 fails.
Basically the algorithm of copy the value up when a delete is performed is not doing the copy correctly.
Way to get around this is to remove the "unique" constrint, but then that makes the relation a many to many.
-----------------------------------------------------------------------------
CREATE TABLE `PERSON`
(
`PRESON_ID` varchar(255) NOT NULL, PRIMARY KEY (PRESON_ID)
)
CREATE TABLE `ADDRESS`
(
`ADDRESS_ID` varchar(255) NOT NULL, PRIMARY KEY (ADDRESS_ID)
)
CREATE TABLE `PERSONADDRESS`
(
`PERSON_ID` varchar(255) NOT NULL
, `PERSON_IDX` integer NOT NULL
, `ADDRESS_ID` varchar(255) NOT NULL UNIQUE, PRIMARY KEY (PERSON_ID, PERSON_IDX)
)
ALTER TABLE `PERSONADDRESS`
ADD INDEX `PERSONADDRESS_FK_PERSON` (`PERSON_ID`),
ADD CONSTRAINT `PERSONADDRESS_FK_PERSON`
FOREIGN KEY (`PERSON_ID`)
REFERENCES PERSON(`PERSON_ID`)
ALTER TABLE `PERSONADDRESS`
ADD INDEX `PERSONADDRESS_FK_ADDRESS` (`ADDRESS_ID`),
ADD CONSTRAINT `PERSONADDRESS_FK_ADDRESS`
FOREIGN KEY (`ADDRESS_ID`)
REFERENCES ADDRESS(`ADDRESS_ID`)
Person.hbm.xml
-------------------------
<list name="AddressList" lazy="false" table="PersonAddress">
<key column="PERSON_ID" />
<index column="PERSON_IDX" />
<many-to-many column="ADDRESS_ID" unique="true" class="Address" />
</list>
Address.hbm.xml
--------------------------
No information about Person, since this is a unidirectional association.
Target doesnt know about the source.
Test psuedocode
-------------------------
//start transaction
Person person = new Person();
Address add1 = new Address();
Address add2 = new Address();
Address add3 = new Address();
person.add(add1);
person.add(add2);
person.add(add3);
// persist to database
person.save
// end transaction
// start transaction
// get back that person from database
person.remove(add1);
// persist to database
person.save <<<<<<<<<<<<<<< FAILS, duplicate key constraint violation
// end transaction
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 7 months
[Hibernate-JIRA] Created: (HHH-2341) ObjectNotFoundException on session.get() on non-existent object
by Timo Thomas (JIRA)
ObjectNotFoundException on session.get() on non-existent object
---------------------------------------------------------------
Key: HHH-2341
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2341
Project: Hibernate3
Type: Bug
Components: core
Versions: 3.2.1
Environment: HSQLDB 1.8.0
Reporter: Timo Thomas
Hibernate version:
3.2.1 GA (same for hibernate-annotations)
Mapping documents:
Parent.java (omitting package and some import declarations)
import javax.persistence.*;
@Entity
public class Parent {
public Integer id;
public Set<Child> children = new HashSet<Child>();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
}
Child.java (omitting package and some import declarations)
import javax.persistence.*;
@Entity
public class Child {
public Integer id;
public Parent parent;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@ManyToOne(optional = false)
@JoinColumn(name = "parent_fk")
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
Code between sessionFactory.openSession() and session.close():
Transaction transaction = session.beginTransaction();
Parent parent = new Parent();
parent.setName("p1");
session.persist(parent);
assertNotNull(parent.getId());
Integer parentId = parent.getId();
Child child = new Child();
child.setName("c1");
child.setParent(parent);
parent.getChildren().add(child);
session.persist(parent);
assertNotNull(child.getId());
Integer childId = child.getId();
transaction.commit();
session.close();
///////////////////////////////////////////
session = sessionFactory.openSession();
transaction = session.beginTransaction();
parent = (Parent) session.load(Parent.class, parentId);
child = (Child) session.load(Child.class, childId);
// child = (Child) session.get(Child.class, childId);
session.delete(parent);
// session.flush(); // !! required if session&transaction is re-opened and child is obtained with load(), otherwise exception on next line - BUG ?
child = (Child) session.get(Child.class, childId);
Full stack trace of any exception that occurs:
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [model.Child#1]
at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:375)
at org.hibernate.event.def.DefaultLoadEventListener.returnNarrowedProxy(DefaultLoadEventListener.java:223)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:187)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
at test.CascadeAnnotationTest.testBug(CascadeAnnotationTest.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at junit.framework.TestCase.runTest(TestCase.java:164)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.framework.TestSuite.runTest(TestSuite.java:228)
at junit.framework.TestSuite.run(TestSuite.java:223)
at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:35)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
The generated SQL (show_sql=true):
Hibernate: insert into Parent (id, name) values (null, ?)
Hibernate: call identity()
Hibernate: insert into Child (id, name, parent_fk) values (null, ?, ?)
Hibernate: call identity()
Hibernate: select parent0_.id as id0_0_, parent0_.name as name0_0_ from Parent parent0_ where parent0_.id=?
Hibernate: select children0_.parent_fk as parent3_1_, children0_.id as id1_, children0_.id as id1_0_, children0_.name as name1_0_, children0_.parent_fk as parent3_1_0_ from Child children0_ where children0_.parent_fk=?
Why is this exception thrown under these circumstances? Am I using the API in an undocumented/disallowed way? If yes, where exactly?
The Hibernate API doc says, that Session.get() returns null if an object can't be found. No exception should be thrown.
However, Session.get() at the end of sample code does return null as expected, if either
a) Session.get() is used instead of load() some lines above (see commented line)
b) the transaction and the session is isn't closed or reopened, respectively
c) Session.flush() is called before the final call to Session.get()
I'd like to understand why Hibernate behaves like this, which I presume is erroneous. I'm a beginner in Hibernate, but I couldn't get any help in the forum.
Timo
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
14 years, 7 months
[Hibernate-JIRA] Created: (HHH-3159) Oracle 11g - desupport of oracle.jdbc.driver
by D. S. (JIRA)
Oracle 11g - desupport of oracle.jdbc.driver
--------------------------------------------
Key: HHH-3159
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3159
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.5
Environment: Hibernate 3.2.5GA, Oracle 11.1.0.6.0.
Reporter: D. S.
With Oracle 11g, the deprecated package oracle.jdbc.driver no longer exists and this causes issues with all OracleDialect classes making it impossible to use Hibernate.
This issue affects all of the following classes:
Oracle9iDialect.java
Oracle9Dialect.java
Oracle10gDialect.java
The line error in question is:
Class types = ReflectHelper.classForName("oracle.jdbc.driver.OracleTypes");
This simply needs to be changed to:
Class types = ReflectHelper.classForName("oracle.jdbc.OracleTypes");
>From the Oracle 11g readme.txt
"In Oracle JDBC release 9.0.1 customer use of the classes
in that package was deprecated. A new package, oracle.jdbc, was
introduced and customers were advised to begin using the
interfaces and classes defined in oracle.jdbc. In every release
since 9.0.1 we have encouraged customers to switch to oracle.jdbc
and stated that oracle.jdbc.driver would be desupported. The time
has come. Customer code that references oracle.jdbc.driver will
not compile and will not execute in this and future releases of
the Oracle JDBC drivers. Please use oracle.jdbc instead."
Thanks.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 7 months
[Hibernate-JIRA] Created: (HHH-3682) OracleDialect with oracle 11g
by akash (JIRA)
OracleDialect with oracle 11g
-----------------------------
Key: HHH-3682
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3682
Project: Hibernate Core
Issue Type: Bug
Affects Versions: 3.2.5
Environment: Oracle 10.2, weblogic 10.3 , java 1.6 , spring 2.0
Reporter: akash
We are calling sql procedures using Hiberante and I have used OracleDialect9 as my hiberante dialect.
These configuration is working fine in weblogic 8.1 but it's failing in weblogic 10.3 with exception "Caused by: java.lang.IllegalAccessException: Class org.hibernate.dialect.Oracle9Dialect can not access a member of class oracle.jdbc.driver.OracleTypes with modifiers ""
" .
I went through the dialect code and found that here is one line "Class types = ReflectHelper.classForName("oracle.jdbc.driver.OracleTypes");" to load OracleTypes where in oracle 11g they have depricated oracle.jdbc.driver package. Now since weblogic 10.3 internally comes with oracle 11g thin driver, hibernate is not able to find OracleTypes class.
So what do u think what i should do to make this work ? Is there any dialect available which can support oracle 11g and solve this problem ? So should i created my own dialect and handle this issue ?
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 7 months