[Hibernate-JIRA] Created: (HHH-6776) Hibernate inserts duplicates into @OneToMany collection
by Damien (JIRA)
Hibernate inserts duplicates into @OneToMany collection
-------------------------------------------------------
Key: HHH-6776
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-6776
Project: Hibernate Core
Issue Type: Bug
Affects Versions: 4.0.0.CR4, 3.6.7
Environment: MySQL 5.1.54
Reporter: Damien
Priority: Minor
Attachments: Test.zip
Consider following entities (getters and setters are omitted for brevity):
{code:java}
@Entity
public class Parent
{
@Id
@GeneratedValue
private int id;
@OneToMany(mappedBy="parent")
private List<Child> children = new LinkedList<Child>();
}
@Entity
public class Child
{
@Id
@GeneratedValue
private int id;
@ManyToOne
private Parent parent;
}
{code}
Now consider following code snippet, which persists one parent and one child entity and then prints the children of the parent.
{code:java}
// persist parent entity in a transaction
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Parent parent = new Parent();
em.persist(parent);
int id = parent.getId();
em.getTransaction().commit();
em.close();
// relate and persist child entity in a new transaction
em = emf.createEntityManager();
em.getTransaction().begin();
parent = em.find(Parent.class, id);
// *: parent.getChildren().size();
Child child = new Child();
child.setParent(parent);
parent.getChildren().add(child);
em.persist(child);
System.out.println(parent.getChildren()); // -> [Child@36bf7916, Child@36bf7916]
em.getTransaction().commit();
em.close();
{code}
The child entity is wrongly being inserted twice into the list of children of the parent entity.
When doing one of the following, the code works fine (no duplicate entries in the list):
- remove the mappedBy attribute in the parent entity
- perform some read operation on the list of children (e.g. uncomment line marked by *)
Also, when testing against another persistence provider, the code works as expected (no duplicates).
Take a look at axtavt's [answer|http://stackoverflow.com/questions/7903800/hibernate-inserts-dupli...] to my post on Stack Overflow. He seems to know why this problem occurrs.
I have attached a simple JUnit test for this issue.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 4 months
[Hibernate-JIRA] Created: (HHH-5988) HBM2DLL creates invalid Create Table statement on MySQL 5.5.x because keyword *TYPE* is forbidden now
by Sebastian Wagner (JIRA)
HBM2DLL creates invalid Create Table statement on MySQL 5.5.x because keyword *TYPE* is forbidden now
-----------------------------------------------------------------------------------------------------
Key: HHH-5988
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5988
Project: Hibernate Core
Issue Type: Bug
Affects Versions: 3.6.1
Reporter: Sebastian Wagner
In the latest MySQL Version the query that hbm2dll produces:
create table adresses (adresses_id bigint not null, additionalname varchar(255), comment_field varchar(255), fax varchar(255), starttime datetime, state_id bigint, street varchar(255), town varchar(255), updatetime datetime, zip varchar(255), deleted varchar(255), email varchar(255), phone varchar(255), primary key (adresses_id)) TYPE=MyISAM
will throw an error because of *TYPE=MyISAM* its name is now *ENGINE=MyISAM*
so the complete query would be:
create table adresses (adresses_id bigint not null, additionalname varchar(255), comment_field varchar(255), fax varchar(255), starttime datetime, state_id bigint, street varchar(255), town varchar(255), updatetime datetime, zip varchar(255), deleted varchar(255), email varchar(255), phone varchar(255), primary key (adresses_id)) ENGINE=MyISAM
Unfortunally there seems to be neither a fix nor workaround for that Issue yet.
--
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
12 years, 4 months
[Hibernate-JIRA] Created: (HHH-2318) Sometimes wrong classloader used for proxy interfaces
by Jan Wiemer (JIRA)
Sometimes wrong classloader used for proxy interfaces
-----------------------------------------------------
Key: HHH-2318
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2318
Project: Hibernate3
Type: Bug
Components: core
Versions: 3.2.1
Reporter: Jan Wiemer
For some of our business classes we used a Mapping declaring the class to be lazy initialized and providing a proxy interface like e.g.:
<class name="TestClassImpl" proxy="TestClass" table="testTable" lazy="true"> ... </class>
Using classes mapped this way - e.g. as endpoint of a one to one relation - sporadically leads to exceptions like the following:
org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of test.AbstractTestClass2Impl.testField
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:104)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:337)
at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:200)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3514)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:129)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:842)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.doList(Loader.java:2211)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2095)
at org.hibernate.loader.Loader.list(Loader.java:2090)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:388)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at org.hibernate.impl.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:804)
Note that the application is residing in a different classloader than hibernate (and CGLIB...).
Examining the situation we see that the value passed to the setter was a CGLIB proxy. Internally the proxy stores an array of interfaces the proxy should implement. In our situation this interface contains the HibernateProxy interface and our business interface provided as proxy interface in the mapping. In this interface array we checked the classloader of the interfaces. As expected the HibernateProxy interface is loaded by the system classloader and our interface was loaded by our custom classloader. However examining the actual interfaces of the proxy (with proxy.getClass().getInterfaces()[i].getClassLoader() for all i) shows that all interfaces are loaded with the system classloader. This causes the exception above.
Doing some more experiments we experience that the problem does not occur all the time. Sometimes the actual proxy interfaces are as expected (the HibernateProxy interface is loaded by the system classloader and our interface was loaded by our custom classloader). We notice that each time the test failed the HibernateProxy was the first interface in the interface array stored in the proxy.
Some experiments with the CGLIB (the Enhancer class) shows us that (if there is no superclass given) they use the classloader of the first passed interface as default classloader (compare method net.sf.cglib.proxy.Enhancer.getDefaultClassLoader()).
Finally we find out that hibernate passes the proxy interfaces in an arbitrary order since they are using a HashSet for the proxy interfaces in the method org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter). This Hash set is passed to the method org.hibernate.proxy.pojo.cglib.CGLIB_ProxyFactory.postInstantiate(...). There it is simply converted to an Array (leading to a randomized order).
As a workaround it is possible to patch the class org.hibernate.proxy.pojo.cglib.CGLIB_ProxyFactory and add reorganize the array if the HibernateProxy interface is the first one:
this.interfaces = (Class[]) interfaces.toArray(NO_CLASSES);
//----->PATCH<--------
if(this.interfaces.length > 1) {
Class firstIfc = this.interfaces[0];
if(firstIfc.getName().startsWith("org.hibernate")) {
this.interfaces[0] = this.interfaces[1];
this.interfaces[1] = firstIfc;
System.err.println("Replace: " + firstIfc.getName() + " by " + this.interfaces[0].getName());
}
}
//--------------------
After applying this patch everything woks as expected.
Compare with the discussion in:
http://forum.hibernate.org/viewtopic.php?p=2334617#2334617
--
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
12 years, 4 months
[Hibernate-JIRA] Created: (HHH-6874) java.lang.ClassCastException in JavassistLazyInitializer.getProxy
by Vladimir Tsichevski (JIRA)
java.lang.ClassCastException in JavassistLazyInitializer.getProxy
-----------------------------------------------------------------
Key: HHH-6874
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-6874
Project: Hibernate Core
Issue Type: Bug
Components: core
Affects Versions: 3.6.8
Environment: Ubuntu Linux 11.04 x64, JDK 1.6
Reporter: Vladimir Tsichevski
The following Exception occurs:
Caused by: java.lang.ClassCastException: ClassX_$$_javassist_129 cannot be cast to javassist.util.proxy.ProxyObject
at the following line
( ( ProxyObject ) proxy ).setHandler( instance );
where ClassX is a persistent entity with @ManyToOne references of type FetchType.LAZY. The error was not occurred until the FetchType.LAZY modifier was added.
The full stack trace:
Thread [main] (Suspended (exception ClassCastException))
JavassistLazyInitializer.getProxy(Class, String, Class, Class[], Method, Method, CompositeType, Serializable, SessionImplementor) line: 147
JavassistProxyFactory.getProxy(Serializable, SessionImplementor) line: 71
PojoEntityTuplizer(AbstractEntityTuplizer).createProxy(Serializable, SessionImplementor) line: 631
SingleTableEntityPersister(AbstractEntityPersister).createProxy(Serializable, SessionImplementor) line: 3736
DefaultLoadEventListener.createProxyIfNecessary(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType, PersistenceContext) line: 360
DefaultLoadEventListener.proxyOrLoad(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 281
DefaultLoadEventListener.onLoad(LoadEvent, LoadEventListener$LoadType) line: 152
SessionImpl.fireLoad(LoadEvent, LoadEventListener$LoadType) line: 1090
SessionImpl.internalLoad(String, Serializable, boolean, boolean) line: 1038
ManyToOneType(EntityType).resolveIdentifier(Serializable, SessionImplementor) line: 630
ManyToOneType(EntityType).resolve(Object, SessionImplementor, Object) line: 438
TwoPhaseLoad.initializeEntity(Object, boolean, SessionImplementor, PreLoadEvent, PostLoadEvent) line: 139
QueryLoader(Loader).initializeEntitiesAndCollections(List, Object, SessionImplementor, boolean) line: 982
QueryLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 857
QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 274
QueryLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2542
QueryLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line: 2276
QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2271
QueryLoader.list(SessionImplementor, QueryParameters) line: 459
QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 365
HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 196
SessionImpl.list(String, QueryParameters) line: 1268
QueryImpl.list() line: 102
QueryImpl<X>.getResultList() line: 246
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 4 months
[Hibernate-JIRA] Created: (HHH-3603) Hibernate custome classloader
by Behrang Javaherian (JIRA)
Hibernate custome classloader
-----------------------------
Key: HHH-3603
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3603
Project: Hibernate Core
Issue Type: New Feature
Affects Versions: 3.3.0.GA
Reporter: Behrang Javaherian
We are trying to use hibernate in a OSGi like kind of environment. We have a code module that creates the session factory. We want to be able to add classes to session factory and recreated the session factory as needed. But hibernate is always using the current class loader which cause class cast exception if we try to add model classes from child bundles (which has their own class loader). To overcome this issue we had to patch the hibernate internal ReflectHelper and change the classForNameMethod to this:
return PlugableClassFinder.getInstance().classForName(name);
and here is the code for PlugableClassFinder class:
public class PlugableClassFinder {
private Set<ClassLoader> classLoaders = new HashSet<ClassLoader>();
public Class classForName(String name) throws ClassNotFoundException {
try {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if ( contextClassLoader != null ) {
return contextClassLoader.loadClass(name);
}
}
catch ( Throwable t ) {
}
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
}
//now look into the registerred class loaders
for (ClassLoader classLoader : classLoaders) {
try {
return classLoader.loadClass(name);
} catch (ClassNotFoundException e) {
}
}
throw new ClassNotFoundException("Cannot find class: " + name);
}
public void registerClassLoader(ClassLoader classLoader) {
classLoaders.add(classLoader);
}
public void deregisterClassLoader(ClassLoader classLoader) {
classLoaders.remove(classLoader);
}
private static final PlugableClassFinder instance = new PlugableClassFinder();
public static PlugableClassFinder getInstance() {
return instance;
}
}
Now every bundle will register its class loader with PlugableClassFinder class.
Maybe hibernate should either allow plugging new class loaders to resolve classes or provide a hook o an interface that we can implement to replace the internal class resolving mechanism. For the moment our approach if working for us.
Regards
Behrang Javaherian
http://www.beyondng.com
--
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
12 years, 4 months