[Hibernate-JIRA] Created: (HHH-2351) PersistentMap incorrectly flags rows for insertion when data contains NULLs
by Matt Doran (JIRA)
PersistentMap incorrectly flags rows for insertion when data contains NULLs
---------------------------------------------------------------------------
Key: HHH-2351
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2351
Project: Hibernate3
Type: Bug
Components: core
Versions: 3.0.5, 3.2.1
Environment: Found in 3.0.5, but the code in 3.2.1 contains the same error.
Reporter: Matt Doran
Attachments: partial-map-null-fix.patch
There is a bug in the org.hibernate.collection.PersistentMap implementation that can cause hibernate to try to insert duplicate rows when the map values from the database contain null.
The issue is caused when incorrectly testing if an row exists in a Map. The persistent map testing whether map values are == null instead of checking to see if the key exists. i.e. using Map.get(key) == null instead of Map.containsKey(key).
This is incorrect, because the map values are allowed to contain null.
This problem can bee seen in the following code:
public boolean needsInserting(Object entry, int i, Type elemType)
throws HibernateException {
final Map sn = (Map) getSnapshot();
Map.Entry e = (Map.Entry) entry;
return e.getValue()!=null && sn.get( e.getKey() )==null;
}
If the map contains an entry: key1 -> NULL , and we try to update the value , then the above code will incorrectly result in a new row being attempted to be inserted (instead of updated).
Instead of checking whether the values == null the Map.containKey() method should be used.
I think similar bugs also exist in the "needsUpdating" and "getDeletes" methods. I've attached a possible patch for the "needsInserting" and "needsUpdating" methods, but I don't understand everything that's going on here or the code in "getDeletes" .... but I'm sure you guys will know the right answer!
SIDE NOTE:
The reason this has just started causing us an issue in our product (PaperCut NG), is that we are porting to Oracle, which turns empty strings into NULLs (which is annoying). For other databases we stored blank strings in the values, but in Oracle they become NULLs (whether we like it or not). We then start getting errors about violating uniqueness constraints when Hibernate incorrectly these attempts to re-insert the rows in the database.
This is of critical importance to us. In the short-term, our work-around might involve just deleting rows that contain NULL.
--
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
17 years, 3 months
[Hibernate-JIRA] Commented: (HHH-1123) Cannot put more than 1000 elements in a InExpression
by Christian Gruber (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1123?page=c... ]
Christian Gruber commented on HHH-1123:
---------------------------------------
Just for the sake of completeness: This bug does not only affect the Criteria API, but also HQL. I'm not sure whether the proposed patch can also fix that.
> Cannot put more than 1000 elements in a InExpression
> ----------------------------------------------------
>
> Key: HHH-1123
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1123
> Project: Hibernate3
> Type: Bug
> Components: core
> Versions: 3.1 rc2, 3.2.0.alpha1
> Environment: Oracle 9i
> Reporter: Alexis Seigneurin
> Attachments: patch.txt
>
> Original Estimate: 1 hour
> Remaining: 1 hour
>
> The number of elements that we can put in a "in" expression is limited to a certain amount (1000 for Oracle, for instance). When creating a criteria query, the org.hibernate.criterion.InExpression class should split the expression into several smaller ones.
> Attached is a patch which splits the expression by slices of 500 elements. For example, if we have 1001 elements to put in the "in" expression, the result would be :
> (entity.field in (?, ?, ?...) or entity.field in (?, ?, ?...) or entity.field in (?))
> The surrounding parantheses are useful to avoid problems with other conditions (a "and" condition taking over the one of the "or" conditions).
--
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
17 years, 3 months
[Hibernate-JIRA] Updated: (HHH-1599) ConstraintViolationException returns null with PostgresDialect (Solution included)
by Benoit Goudreault-Emond (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1599?page=all ]
Benoit Goudreault-Emond updated HHH-1599:
-----------------------------------------
Attachment: HHH-1599.patch
The attached patch provides what I believe to be a more robust solution. In general, if one is extracting the error code from an SQLException obtained through getNextException(), one should extract the constraint name from that exception's message, not the original exception's. This has been validated to work on Postgres, but I don't really have access to the other databases.
I'll attach a patch that modifies only the PostgresDialect (which is the one that should be applied if you just want to fix that one without risking the other dialects).
> ConstraintViolationException returns null with PostgresDialect (Solution included)
> ----------------------------------------------------------------------------------
>
> Key: HHH-1599
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1599
> Project: Hibernate3
> Type: Bug
> Components: core
> Versions: 3.1.3
> Environment: Hibernate 3.1.3 , Postgres 8.1.2 (i686), postgresql-8.2dev-501.jdbc.jar
> Reporter: Niclas Lindberg
> Priority: Minor
> Attachments: HHH-1599.patch
>
> Original Estimate: 3 minutes
> Remaining: 3 minutes
>
> ConstraintViolationException.getConstraintName() returns null. The problem is that the message being parsed comes from the SqlException that is the inputparameter to extractConstraintName(SqlException) in ViolatedConstraintNameExtracter.
> Solution. The message provided by sqlException.getMessage() is "batch bla bla something" but the correct Exception message to parse is sqlException.getNextException().getMessage()
--
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
17 years, 3 months
[Hibernate-JIRA] Commented: (HHH-298) allow joins in filters
by Shawn Clowater (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-298?page=co... ]
Shawn Clowater commented on HHH-298:
------------------------------------
I've got no problem doing the work since I'm really the one asking for the functionality, viva open source.
However, I do have some questions on how you foresaw this working. In the simple example you provided you do a simple inner join to a child table. However, how were you going to inject the join table into the FROM clause (and ensure that it doesn't conflict with the initial query).? Without the table in the FROM clause I would assume that the sql parser wouldn't know what the alias is and throw an exception.
In my case I really only simply needed to force an inner join on a non-lazy loaded collection so that it would be added to the FROM clause and then the collection filter actually handles the rest very nicely. (and in this case I wouldn't even need the filter at the entity level). However, this original functionality enhancement also seemed like a good way to achieve the same thing and seems a bit less exotic.
What I'm trying to accomplish for my case is to correlate multiple filters at the entity level that end up being tackled with subqueries.
I'm essentially trying to get the generated SQL to go
From:
this_.AGMT_CNTRCT_LINE_ID = version.AGMT_CNTRCT_LINE_ID
AND version.CREATE_DATE = (
SELECT
MAX(b.CREATE_DATE)
from
AGMT_CNTRCT_LINE_V b
WHERE
version.AGMT_CNTRCT_LINE_ID = b.AGMT_CNTRCT_LINE_ID
AND ? < b.VERSION_END_DATE
AND ? > b.VERSION_START_DATE
)
AND version.ACTIVE_FLG=?
)
and this_.AGMT_CNTRCT_LINE_ID IN (
SELECT
version.AGMT_CNTRCT_LINE_ID
FROM
AGMT_CNTRCT_LINE_V version
WHERE
this_.AGMT_CNTRCT_LINE_ID = version.AGMT_CNTRCT_LINE_ID
AND ? < version.INACTIVE_DATE
AND ? > version.EFFECTIVE_DATE
)
To:
where
this_.AGMT_CNTRCT_LINE_ID IN (
SELECT
version.AGMT_CNTRCT_LINE_ID
FROM
AGMT_CNTRCT_LINE_V version
WHERE
this_.AGMT_CNTRCT_LINE_ID = version.AGMT_CNTRCT_LINE_ID
AND version.CREATE_DATE = (
SELECT
MAX(b.CREATE_DATE)
from
AGMT_CNTRCT_LINE_V b
WHERE
version.AGMT_CNTRCT_LINE_ID = b.AGMT_CNTRCT_LINE_ID
AND ? < b.VERSION_END_DATE
AND ? > b.VERSION_START_DATE
)
AND version.ACTIVE_FLG=?
AND ? < version.INACTIVE_DATE
AND ? > version.EFFECTIVE_DATE
)
Where the INACTIVE/EFFECTIVE DATE piece is a separate filter. The filters working together should give the record that has a version that is the most recently created that fall within that start/end date, is active and falls within the inactive/effective date.
In the first case I can actually return something as long as it's most recent version is active and falls within the start date and then has at least one version that was effective at some point (might be a different version). When the collection is loaded the the collection filter is applied as in the 2nd case and then we end up with an Entity that has no versions which is what we were trying to filter against.
So, barring any snarls with trying to inject the joined table back into the FROM clause, what do you think of the following? Having some sort of nested construct that I could apply the initial subselect and then the remaining filters would be applied against it. I know it doesn't really address your original idea but it would reduce the number of subselects I'm currently using and they'd actually work properly.
So essentialy I would end up with some construct that would generate the
this_.AGMT_CNTRCT_LINE_ID IN (
SELECT
version.AGMT_CNTRCT_LINE_ID
FROM
AGMT_CNTRCT_LINE_V version
WHERE
this_.AGMT_CNTRCT_LINE_ID = version.AGMT_CNTRCT_LINE_ID
And then my subsequent filters would get applied to this fragment.
> allow joins in filters
> ----------------------
>
> Key: HHH-298
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-298
> Project: Hibernate3
> Type: Improvement
> Components: core
> Reporter: Steve Ebersole
> Assignee: Steve Ebersole
>
>
> For the sake of performance with complex filters, it'd be nice to allow users to specify joins fragments to be added to the filter tags. Somthing like:
> <filter name="myFilter">
> <filter-join table="MyPermissionTable">
> <condition>
> {this}.id =
> {MyPermissionTable}.object_id
> </condition>
> </filter-join>
> <![CDATA[
> {MyPermissionTable}.user_id =
> :userId
> AND
> {MyPermissionTable}.perm_flg <
> :userPermLevel
> ]]>
> </filter>
--
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
17 years, 3 months