[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-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-2808) CLONE -Impossible to define caching for a subclass's collection in hibernate.cgf.xml
by Sebastien Blind (JIRA)
CLONE -Impossible to define caching for a subclass's collection in hibernate.cgf.xml
-------------------------------------------------------------------------------------
Key: HHH-2808
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2808
Project: Hibernate3
Issue Type: Bug
Components: caching (L2)
Affects Versions: 3.2.5
Environment: Hibernate 3.2.5
Sybase
Reporter: Sebastien Blind
Basically, hibernate allows to define <cache usage="transactional"/> inside the subclass mapping, i.e.
<subclass name="SubClass" extends="BaseClass" discriminator-value="xxx">
<bag name="subClassLinks" lazy="false" inverse="true" batch-size="100">
<cache usage="transactional" region="xxx"/>
<key column="xxx" not-null="true"/>
<one-to-many class="xxx"/>
</bag>
<join table="xxx">
</join>
</subclass>
but it's not allowed to do the same using <collection-cache collection="subClass.myCollection" region="xxx" usage="transactional"/>.
It throws:
Exception in thread "main" org.hibernate.MappingException: Cannot cache an unknown collection: subClass.myCollection
at org.hibernate.cfg.Configuration.setCollectionCacheConcurrencyStrategy(Configuration.java:1984)
at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1568)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1534)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1508)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1428)
--
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-2851) ParameterTranslationsImpl fails to correctly determine parameter type
by Alex Savitsky (JIRA)
ParameterTranslationsImpl fails to correctly determine parameter type
---------------------------------------------------------------------
Key: HHH-2851
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2851
Project: Hibernate3
Issue Type: Bug
Components: query-hql
Affects Versions: 3.2.5
Reporter: Alex Savitsky
Priority: Minor
For the conditions in the form "(:param IS NULL OR alias.someField = :param)", the HQL parses would not correctly determine the type of param, unless the conditions are swapped like "(alias.someField = :param OR :param IS NULL)". The reason is that NamedParamTempHolder classes are created for all parameter entries, in the order they appear in the query. The first occurrence (:param IS NULL) would have its expectedType set to null, and the second occurrence would use the param holder created by the first occurrence, without checking whether it can improve it in any way (which it can - the expectedType for second occurrence is correctly determined to be Long).
Proposed fix would be to check for this particular condition, enhancing paramHolder if possible, with new information:
old code:
if ( paramHolder == null ) {
paramHolder = new NamedParamTempHolder();
paramHolder.name = namedSpec.getName();
paramHolder.type = namedSpec.getExpectedType();
namedParameterMap.put( namedSpec.getName(), paramHolder );
}
new code:
if ( paramHolder == null ) {
paramHolder = new NamedParamTempHolder();
paramHolder.name = namedSpec.getName();
paramHolder.type = namedSpec.getExpectedType();
namedParameterMap.put( namedSpec.getName(), paramHolder );
+ } else if (paramHolder.getExpectedType() == null && namedSpec.getExpectedType() != null) {
+ paramHolder.type = namedSpec.getExpectedType();
}
--
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, 5 months
[Hibernate-JIRA] Created: (ANN-625) @OrderBy usage on a joined classes (when using join table) produces incorred SQL syntax.
by Dima Gutzeit (JIRA)
@OrderBy usage on a joined classes (when using join table) produces incorred SQL syntax.
----------------------------------------------------------------------------------------
Key: ANN-625
URL: http://opensource.atlassian.com/projects/hibernate/browse/ANN-625
Project: Hibernate Annotations
Issue Type: Bug
Affects Versions: 3.3.0.ga
Reporter: Dima Gutzeit
Please consider the following mapping :
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@IndexColumn(name = "ListIndex")
@JoinTable(name = "odp_rulemanipulatorjoin", joinColumns = @JoinColumn(name = "RoutingRuleId"), inverseJoinColumns = @JoinColumn(name = "ManipulatorComponentId"))
@OrderBy(value = "priority asc")
public List<RoutingManipulationComponent> getManipulators() {
if (manipulators == null) {
manipulators = new ArrayList<RoutingManipulationComponent>();
}
return manipulators;
}
***********************************
@Entity(name = "RoutingManipulationComponent")
@DiscriminatorValue("RoutingManipulationComponent")
public abstract class RoutingManipulationComponent extends RoutingComponent implements Initializable {
/**
* Applies the manipulation to the given context.
*
* @param context the routing context to manipulate
* @return true if any manipulation was applied, false if no manipulation
* occurred
*/
public abstract boolean apply(RoutingContext context);
}
******************************************
@Entity(name = "RoutingComponent")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "RoutingComponentType", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("RoutingComponent")
@Table(name = "odp_routingcomponent")
public abstract class RoutingComponent extends DialPlanProvisionalEntity {
@Deprecated
public RoutingComponent() {
// blank
}
/**
* @param name
* @param description
*/
public RoutingComponent(String name, String description) {
super(name, description);
}
}
*******************************
@MappedSuperclass
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public abstract class DialPlanProvisionalEntity extends ProvisionalEntity
implements Initializable {
private Long entityId;
private boolean visible = true;
private int priority;
/**
* Not for direct instantiation - this constructor also serves as public
* constructor for hibernate, jax-ws etc. <br>
*/
@Deprecated
public DialPlanProvisionalEntity() {
this("(no name set)", "(no description set)");
}
/**
* @param name
* @param description
*/
public DialPlanProvisionalEntity(String name, String description) {
creationDate = GregorianCalendar.getInstance(); // now
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Override
public Long getId() {
return entityId;
}
@Override
public void setId(Long ruleCollectionId) {
this.entityId = ruleCollectionId;
}
/**
* @return Returns the priority.
*/
public int getPriority() {
return priority;
}
/**
* @param priority The priority to set.
*/
public void setPriority(int priority) {
this.priority = priority;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) {
return false;
}
final ProvisionalEntity other = (ProvisionalEntity) o;
return MiscUtils.equalOrBothNull(this.getName(), other.getName());
}
@Override
public int hashCode() {
String name = this.getName();
return getClass().getName().hashCode() + 13 * name.hashCode();
}
}
The above mapping should use the "priority" field to the ordering.
SQL that is produced is :
select criteria0_.RoutingRuleId as RoutingR1_1_, criteria0_.CriteriaComponentId as Criteria2_1_,
criteria0_.ListIndex as ListIndex1_,
routingcri1_.id as id73_0_,
routingcri1_.creationDate as creation3_73_0_,
routingcri1_.description as descript4_73_0_,
routingcri1_.lastModificationDate as lastModi5_73_0_,
routingcri1_.name as name73_0_,
routingcri1_.predefined as predefined73_0_,
routingcri1_.status as status73_0_,
routingcri1_.priority as priority73_0_,
routingcri1_.visible as visible73_0_,
routingcri1_.matcher_id as matcher25_73_0_,
routingcri1_.criterion_id as criterion27_73_0_,
routingcri1_.location_id aslocation26_73_0_,
routingcri1_.RoutingComponentType as RoutingC1_73_0_
from odp_rulecriteriajoin criteria0_
left outer join odp_routingcomponent as routingcri1_ on criteria0_.CriteriaComponentId=routingcri1_.id
where criteria0_.RoutingRuleId=1 order by odp_routingcomponent .priority asc
It is wrong since not the table alias is used in the order by clause, but the real table name.
Mysql fails with exception that odp_rulecriteriajoin.priority is unknown table.
Changing the query to include "order by criteria0_.priority asc" returns the correct result.
--
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, 5 months