[Hibernate-JIRA] Commented: (HHH-772) null in maps are handled inconsistently
by Nelson Murphy (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-772?page=co... ]
Nelson Murphy commented on HHH-772:
-----------------------------------
In case this is useful to anyone else, I ended up forking the Hibernate core (v3.3.1.GA) and modifying PersistentMap to handle null values.
{code:title=PersistentMap.java.ApplyTo.3.3.1.svn.patch|borderStyle=solid}
@@ -182,12 +182,15 @@
}
}
initialize( true );
+ boolean newKey = !map.containsKey( key );
Object old = map.put( key, value );
// would be better to use the element-type to determine
// whether the old and the new are equal here; the problem being
// we do not necessarily have access to the element type in all
// cases
- if ( value != old ) {
+ if ( newKey
+ || value != old
+ || ( (old==null) != (value==null) ) ) {
dirty();
}
return old;
@@ -279,7 +282,7 @@
throws HibernateException, SQLException {
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
Object index = persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
- if ( element!=null ) map.put(index, element);
+ map.put(index, element);
return element;
}
@@ -408,8 +411,12 @@
while ( iter.hasNext() ) {
Map.Entry e = (Map.Entry) iter.next();
Object key = e.getKey();
- if ( e.getValue()!=null && map.get(key)==null ) {
- deletes.add( indexIsFormula ? e.getValue() : key );
+ if ( !map.containsKey(key) ) {
+ if ( !indexIsFormula ) {
+ deletes.add( key );
+ } else if ( e.getValue() != null ) {
+ deletes.add( e.getValue() );
+ }
}
}
return deletes.iterator();
@@ -419,18 +426,17 @@
throws HibernateException {
final Map sn = (Map) getSnapshot();
Map.Entry e = (Map.Entry) entry;
- return e.getValue()!=null && sn.get( e.getKey() )==null;
+ return !sn.containsKey( e.getKey() );
}
- public boolean needsUpdating(Object entry, int i, Type elemType)
- throws HibernateException {
- final Map sn = (Map) getSnapshot();
- Map.Entry e = (Map.Entry) entry;
- Object snValue = sn.get( e.getKey() );
- return e.getValue()!=null &&
- snValue!=null &&
- elemType.isDirty( snValue, e.getValue(), getSession() );
- }
+ public boolean needsUpdating(Object entry, int i, Type elemType)
+ throws HibernateException {
+ final Map sn = (Map) getSnapshot();
+ Map.Entry e = (Map.Entry) entry;
+ Object snValue = sn.get( e.getKey() );
+ return sn.containsKey(e.getKey()) &&
+ elemType.isDirty( snValue, e.getValue(), getSession() );
+ }
public Object getIndex(Object entry, int i, CollectionPersister persister) {
@@ -457,7 +463,7 @@
}
public boolean entryExists(Object entry, int i) {
- return ( (Map.Entry) entry ).getValue()!=null;
+ return map.containsKey( ((Map.Entry) entry).getKey() );
}
final class Clear implements DelayedOperation {
{code}
Again, this patch is for v3.3.1 from a year ago -- I haven't checked to see if the class has changed since then.
> null in maps are handled inconsistently
> ---------------------------------------
>
> Key: HHH-772
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-772
> Project: Hibernate Core
> Issue Type: Improvement
> Components: core
> Reporter: Max Rydahl Andersen
> Fix For: 3.1 beta 1
>
>
> regarding case 00004729.
> group.getUsers().put("something", null);
> Does not result in any insert.
> Inserting "something", null manually into the underlying table and
> when hibernate reads the map will have "something"->null in the map.
--
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, 10 months
[Hibernate-JIRA] Created: (HHH-4880) EntityManager.refresh does not throw EntityNotFoundException for removed entity
by jaikiran (JIRA)
EntityManager.refresh does not throw EntityNotFoundException for removed entity
-------------------------------------------------------------------------------
Key: HHH-4880
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-4880
Project: Hibernate Core
Issue Type: Bug
Components: entity-manager
Affects Versions: 3.5.0-Beta-4
Environment: Hibernate 3.5.0-Beta-4, JBoss AS trunk (from which 6.0.0.M2 will be released), Sun Java 1.6
Reporter: jaikiran
The EntityManager.refresh method says this:
/**
* Refresh the state of the instance from the database,
* overwriting changes made to the entity, if any.
*
* @param entity
* @throws IllegalStateException if this EntityManager has been closed
* @throws IllegalArgumentException if not an entity
* or entity is not managed
* @throws TransactionRequiredException if invoked on a
* container-managed entity manager of type
* PersistenceContextType.TRANSACTION and there is
* no transaction.
* @throws EntityNotFoundException if the entity no longer
* exists in the database
*/
public void refresh(Object entity);
JBoss EJB3 testsuite has a testcase which currents tests that this method works as expected http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/testsuite/src/...
In short, the testcase does this:
MyEntity e = manager.find(MyEntity.class, id);
local.removeEntity(e.id);
try
{
manager.refresh(e);
}
catch (EntityNotFoundException e1)
{
return; // correct
}
Starting 3.5.0-beta-4 of hibernate, this test fails with the following (unexpected) exception:
Caused by: org.hibernate.AssertionFailure: object must be non-null.
at org.hibernate.engine.StatefulPersistenceContext.setReadOnly(StatefulPersistenceContext.java:1340)
at org.hibernate.impl.SessionImpl.setReadOnly(SessionImpl.java:1982)
at org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:154)
at org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:62)
at org.hibernate.impl.SessionImpl.fireRefresh(SessionImpl.java:1108)
at org.hibernate.impl.SessionImpl.refresh(SessionImpl.java:1088)
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:660)
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:636)
at org.jboss.jpa.impl.tx.TransactionScopedEntityManager.refresh(TransactionScopedEntityManager.java:224)
at org.jboss.ejb3.test.regression.ejbthree290.DAOBean.findAndDelete(DAOBean.java:58)
--
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, 10 months
[Hibernate-JIRA] Created: (HHH-4871) Improve Javadoc (and possibly other) documentation for org.hibernate.id.SequenceHiLoGenerator
by Aleksander Adamowski (JIRA)
Improve Javadoc (and possibly other) documentation for org.hibernate.id.SequenceHiLoGenerator
---------------------------------------------------------------------------------------------
Key: HHH-4871
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-4871
Project: Hibernate Core
Issue Type: Task
Components: documentation
Reporter: Aleksander Adamowski
The org.hibernate.id.SequenceHiLoGenerator identifier generator is probably the most misunderstood generator due to poor documentation. Unfortunately, it's also the default for JPA, and this leads to serious problems for many people.
See e.g.:
ANN-354
this forum thread: https://forum.hibernate.org/viewtopic.php?f=9&t=967338&view=next
Many misunderstandings would be avoided, if Javadoc for the org.hibernate.id.SequenceHiLoGenerator class would specify how exactly does the logic work and how should people get the most frequently desired behaviour of ordinary 1:1 sequence from the database (the answer being, use allocationSize=1).
A good, but generic description of how hi/lo algorithm works is on stack overflow: http://stackoverflow.com/questions/282099/whats-the-hi-lo-algorithm
The Hibernate's implementation, when used from a @SequenceGenerator, seems to get a hi value from corresponding database sequence, create an initial identifier by multiplying it by allocationSize, then works up from that, incrementing by 1 until the allocation is depleted - then it repeats the procedure by getting a new fresh sequence value, multiplying it etc.
The docs should also explain how this strategy is beneficial to performance in distributed environments and why it has been chosen as the default over simple 1:1 sequence handling.
--
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, 10 months
[Hibernate-JIRA] Created: (HHH-2288) Adding a new ResultTransformer, permitting to instantiate and fill related beans and not to take care of aliases case.
by Nicolas Billard (JIRA)
Adding a new ResultTransformer, permitting to instantiate and fill related beans and not to take care of aliases case.
----------------------------------------------------------------------------------------------------------------------
Key: HHH-2288
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2288
Project: Hibernate3
Type: Improvement
Components: query-sql, query-hql, query-criteria
Versions: 3.2.1
Environment: Developped based on hibernate v 3.2.1
Reporter: Nicolas Billard
Priority: Minor
Attachments: ResultTransformerImprovement.zip
Are joined to this post 2 classes. Below is the javadoc header of the ResultTransformer class.
May be this could be integrated in next hibernate versions ( certainly with improvements ... :p )
Let me know if anyone finds it useful ...
------------------------------------------------------
* Transforms resultset to value a bean, via setters.
*
* Examples:
*
* bean MyBean as 2 setters :
* - setId : takes an Integer
* - setProduct : takes a Product bean
*
* Product bean as 2 setters :
* - setId
* - setLib
*
* resultset may have these columns :
* - ID
* - PRODUCT_ID
* - PRODUCT_LIB
*
* A MyBean instance will be created for each tupple,
* and a Product instance will be also created, filled with PRODUCT_ID and PRODUCT_LIB values.
--
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, 10 months
[Hibernate-JIRA] Updated: (HHH-1043) Added HAVING Support to Criteria
by Chris Wilson (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1043?page=c... ]
Chris Wilson updated HHH-1043:
------------------------------
Attachment: GenericLogicalExpression.java
FunctionExpression.java
MultiColumnGroupByProjection.java
I'm attaching a slightly better (IMHO) version of the GroupByHavingProjection. It supports querying on multiple-column properties (e.g. we have a composite primary key and want to group by it), and using any Criterion (Restrictions.*) for the Having clause.
You can use it like this:
{code}
Criterion having = new GenericLogicalExpression(
new FunctionExpression("SUM", "mi.ltuQty"), "<>",
new FunctionExpression("SUM", "mo.ltuQty"));
rl.setProjection(new MultiColumnGroupByProjection("id", having));
{code}
Which results in:
{code:sql}
group by line.id, line.request_site_id
HAVING SUM(mi.ltu_qty) <> SUM(mo.ltu_qty);
{code}
However, it requires a change to CriteriaLoader.getResultColumnOrRow to support multiple columns (composite type properties):
{code}
protected Object getResultColumnOrRow(Object[] row,
ResultTransformer transformer, ResultSet rs, SessionImplementor session)
throws SQLException, HibernateException
{
final Object[] result;
final String[] tableAliases;
CriteriaQueryTranslator translator = getTranslator();
if (translator.hasProjection())
{
Type[] types = translator.getProjectedTypes();
result = new Object[types.length];
int currentColumn = 0;
String[] columnAliases = translator.getProjectedColumnAliases();
for (int i = 0; i < types.length; i++)
{
int span = types[i].getColumnSpan(session.getFactory());
result[i] = types[i].nullSafeGet(rs,
ArrayHelper.slice(columnAliases, currentColumn, span),
session, null);
currentColumn += span;
}
tableAliases = translator.getProjectedAliases();
}
else
{
result = row;
tableAliases = m_UserAliases;
}
return translator.getRootCriteria().getResultTransformer()
.transformTuple(result, tableAliases);
}
{code}
If you need to apply this in a stable release of Hibernate without patching, you can use the RitaCriteriaQuery:
http://rita.wfplogistics.org/trac/browser/rita/src/org/wfp/rita/db/RitaCr...
and call it like this:
{code}
RitaCriteriaQuery query = new RitaCriteriaQuery(criteria,
m_Environment.getSessionFactory());
return ((SessionImplementor) m_Session).listCustomQuery(query,
query.getQueryParameters());
{code}
> Added HAVING Support to Criteria
> --------------------------------
>
> Key: HHH-1043
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1043
> Project: Hibernate Core
> Issue Type: Patch
> Components: query-criteria
> Affects Versions: 3.1 rc 1
> Environment: 3.1 rc 1
> Reporter: Tony Voss
> Priority: Minor
> Attachments: criteria-having-improvement.patch, criteria-having-improvement.zip, FunctionExpression.java, GenericLogicalExpression.java, GroupByHavingProjection.java, MultiColumnGroupByProjection.java
>
>
> I've added support for HAVING clauses to Criteria. Attached are my code changes.
--
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, 10 months