openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Heath Thomann (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (OPENJPA-1854) A 'find' or 'query' may return multiple instances of Entities which contain Embeddables, where the Embeddables use String identities, if the id value has trailing spaces.
Date Wed, 11 Dec 2013 21:23:07 GMT

    [ https://issues.apache.org/jira/browse/OPENJPA-1854?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13845733#comment-13845733
] 

Heath Thomann commented on OPENJPA-1854:
----------------------------------------

It has recently came to my attention that this JIRA is still open, and furthermore the details
of a solution not documented.  Let me do so now and explain the conclusion myself and Fay
Wang came up with when working with a few customers on this issue.  Basically the solution
can be made via user code as I'll explain in a moment and is not a bug in OpenJPA code.  I
was a bit premature in opening a JIRA and assuming their was a bug in OpenJPA code.  Let me
first state that OPENJPA-1501 fixed an issue where a (single) Primay Key defined as a String
contained trailing white space.  In this case, OpenJPA knows the type of the field (String),
and has options available to remove trailing white space.  As such, a decision was made in
the JIRA to strip the trailing white space from a String PK.  This has been the solution since
OpenJPA 2.0.x.  In this JIRA, I assumed that the issue was similar and that OpenJPA could
remove trailing white space from compound PKs, such as @EmbeddedId.  However, in this case
OpenJPA has less control over these objects, or I should say the fields contained within them
(these are opaque object from OpenJPA's point of view).  Furthermore, it is likely that any
trailing white space for String fields in these objects are either a) put there by the user,
or b) represents what is in the database.  That is, for #a, when a user creates an @Embeddable,
it is possible they may add trailing white space to String fields.  OpenJPA has no control
over this.  So for a finder method where a user passes in an @Embeddable, OpenJPA simply uses
whatever the user gives the finder.  If the user pads a String field with white space, then
that is what is used by OpenJPA.  One customer may argue OpenJPA should attempt to remove
white space, while another may find that problematic.  For #b, if an @Embeddable's string
fields are mapped to a char field in the database, most (all?) databases will return a string
padded with white space up to the length of a char (e.g. for a char(10), and string 'test',
the database will return 'test      ' - a string with 6 white spaces).  This is likely not
the case if the field is mapped to a varchar.  So if a user executes a query to retrieve an
entity with an @EmbeddedId, and if the @Embeddable's string fields are mapped to a char field
in the database, the resultant @Embeddable's string field will contain trailing white space
up to the length of the char.  Again, this is out of OpenJPA's control and is simply a representation
of what is in the database.  Obviously a solution is to use a varchar rather than char to
avoid trailing white space.  :)  
Having said all of that, the fix here is simple and can be performed in user code by doing
one of the following two options:  

1) Permanently remove trailing white space from within the EmbeddableId's constructor AND setter methods.                          
2) Permanently remove trailing white space from within the EmbeddableId's equals AND hashCode methods.                             

As an example, if you look at the test I had provided in the JIRA (OPENJPA-1854-1.2.x.test),
to allow the test to work we would remove the white space as follows:

import org.apache.commons.lang.StringUtils;
....
	public ObjectIDEntityPK(String name, String version) {
		super();
		this.name = (name == null ? name : StringUtils.stripEnd(name,null));
		this.version = (version == null ? version : StringUtils.stripEnd(version,null)) ;
	}	

	public void setName(String name) {
		this.name = (name == null ? name : StringUtils.stripEnd(name,null));
	}

	public void setVersion(String version) {
		this.version = (version == null ? version : StringUtils.stripEnd(version,null));
	}

	public int hashCode() {
		name = StringUtils.stripEnd(name,null);
		version = StringUtils.stripEnd(version,null);
		
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((version == null) ? 0 : version.hashCode());
		return result;
	}

	public boolean equals(Object obj) {
		name = StringUtils.stripEnd(name,null);
		version = StringUtils.stripEnd(version,null);
		
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ObjectIDEntityPK other = (ObjectIDEntityPK) obj;
		other.name = StringUtils.stripEnd(other.name,null);
		other.version = StringUtils.stripEnd(other.version,null);
		
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (version == null) {
			if (other.version != null)
				return false;
		} else if (!version.equals(other.version))
			return false;
		return true;
	}


Thanks,

Heath Thomann

> A 'find' or 'query' may return multiple instances of Entities which contain Embeddables,
where the Embeddables use String identities, if the id value has trailing spaces.
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: OPENJPA-1854
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1854
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: kernel
>    Affects Versions: 1.2.2, 1.3.0, 2.0.0
>            Reporter: Heath Thomann
>            Assignee: Heath Thomann
>         Attachments: OPENJPA-1854-1.2.x.test
>
>
> This issue is very similar to that of OPENJPA-1501, with one twist.......I've found that
when you have an Embeddable, which has Strings as the keys/ids, openJPA code puts the Embeddable
into an ObjectID by design, rather than a StringID....recall, the fix to OJ1501 was to strip
white space from the end of a user's String key when that String was placed into a StringID.
 So, the strings in an Embeddable would also need to be stripped, just as was done in OJ-1501,
but unfortunately it would seem to be harder to do so for Embeddables since openJPA code doesn't
necessarily know what types are contained in the Embed.
> I've created a JUnit test case which has three test methods.  The test is attached here.



--
This message was sent by Atlassian JIRA
(v6.1.4#6159)

Mime
View raw message