[Hibernate-JIRA] Created: (ANN-630) @ManyToMany and @Index
by Peter K. Guldbæk (JIRA)
@ManyToMany and @Index
----------------------
Key: ANN-630
URL: http://opensource.atlassian.com/projects/hibernate/browse/ANN-630
Project: Hibernate Annotations
Issue Type: Bug
Affects Versions: 3.3.0.ga
Environment: Windows Vista
java version "1.5.0_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03)
Java HotSpot(TM) Client VM (build 1.5.0_11-b03, mixed mode)
Reporter: Peter K. Guldbæk
I have trouble adding an index to a column of a table which is part of a many-to-many property mapping. The following example causes a NullPointerException when generating the DDL (the exception can be seen at the end of my post):
@Entity @Table(name="usr")
public class User implements Serializable
{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Integer id;
@ManyToMany(targetEntity=Target.class, cascade={})
@Index(name="fkey_usr_target", columnNames="usr_id")
@JoinTable(name="usr_target",
joinColumns=@JoinColumn(name="usr_id"),
inverseJoinColumns=@JoinColumn(name="target_id"))
public Collection<Target> targets;
}
@Entity @Table(name="target")
public class Target implements Serializable
{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Integer id;
@Basic
public String myValue;
}
NullPointerException thrown when an @Index annotation is used with a @ManyToMany:
java.lang.NullPointerException
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1594)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:733)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:498)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:277)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1115)
at org.hibernate.tool.ant.ConfigurationTask.getConfiguration(ConfigurationTask.java:56)
at org.hibernate.tool.ant.HibernateToolTask.getConfiguration(HibernateToolTask.java:299)
at org.hibernate.tool.ant.Hbm2DDLExporterTask.execute(Hbm2DDLExporterTask.java:45)
at org.hibernate.tool.ant.HibernateToolTask.execute(HibernateToolTask.java:183)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor19.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
at org.apache.tools.ant.Project.executeTarget(Project.java:1298)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
at org.apache.tools.ant.Main.runBuild(Main.java:698)
at org.apache.tools.ant.Main.startAnt(Main.java:199)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
--
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-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
[Hibernate-JIRA] Created: (HHH-5962) Custom POJO Loading strategy for cglib and javassist
by Ilya Samartsev (JIRA)
Custom POJO Loading strategy for cglib and javassist
----------------------------------------------------
Key: HHH-5962
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5962
Project: Hibernate Core
Issue Type: Bug
Components: core
Affects Versions: 3.6.1
Environment: Hibernate 3.6.1, PostgreSQL, OSGi
Reporter: Ilya Samartsev
I use hibernate in OSGi-enabled environment and have found a strange class-loading behaviour of the initializer proxies. The problem is that it's not possible to define simple domain-model OSGi bundles which have pojo-based classes to be enhanced by hibernate without importing org.hibernate.*, net.sf.cglib.proxy.*, javassist.util.proxy.*, etc.
Testing environment:
- A Model bundle with pojos and hibernate HBMs(they used by osgi-hibernate loader to enhance them). This bundle doesn't actually require any hibernate/cglib/javassist imports for the reason there are simple pojos in it.
/src/com/example/TestPojoModel.java
/META-INF/mappings/TestPojoModel.hbm.xml
/META-INF/MANIFEST.MF
Expected behaviour:
To have "clean" bundle with pojos without any additional imports(e.g. org.hibernate.* or cglib/javassist).
Enhance these classes without any errors.
Current behaviour:
These pojo-based model bundles require to import a lot of hibernate and cglib or javassist stuff to enhance these pojos. The problem is that hibernate uses the same classloader (from model bundle) to load both pojos and hibernate/codegeneration utility classes. Otherwise it crushes with ClassNotFoundException.
Code explanation:
Javassist ProxyFactory initialization:
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer:
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass( interfaces.length == 1 ? persistentClass : null );
factory.setInterfaces( interfaces );
factory.setFilter( FINALIZE_FILTER );
return factory.createClass();
How javassist loads classes by default:
javassist.util.proxy.ProxyFactory:
protected ClassLoader getClassLoader0() {
ClassLoader loader = null;
if (superClass != null && !superClass.getName().equals("java.lang.Object"))
loader = superClass.getClassLoader();
else if (interfaces != null && interfaces.length > 0)
...
}
return loader;
}
It actually uses the classloader of the persistent class.
My proposition:
To create advanced classloader for ProxyFactory which has custom behaviour:
1. Firstly it tries to load class using the classloader of the persistent class
2. Secondly it tries to use the classloader of the curent hibernate bundle (which definitely has access to its own hibernate classes and imports the classes of the codegeneration libraries)
final ClassLoader platformDelegatingClassLoader = new ClassLoader(persistentClass.getClassLoader()) {
private final ClassLoader platformClassLoader = getClass().getClassLoader();
// on loadClass() it tries to use parent's classloader(parent = persistentClass.getClassLoader() - from the constructor)
// if loadClass() didn't find class it tries to findClass() which is actually overridden to use current context's getClass().getClassLoader()
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return platformClassLoader.loadClass(name);
}
};
ProxyFactory factory = new ProxyFactory() {
@Override
protected ClassLoader getClassLoader() {
return platformDelegatingClassLoader;
}
};
--
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