openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jody Grassel (Commented) (JIRA)" <>
Subject [jira] [Commented] (OPENJPA-2109) Should @Factory methods fire on Entity Identity fields?
Date Tue, 17 Jan 2012 20:10:04 GMT


Jody Grassel commented on OPENJPA-2109:

I mention data integrity/security as a potential issue because a improperly devised transformation
could yield in multiple rows being presented as having the same identity.  The following (obviously
bad) scenario comes to mind: using the entity I described in the example above, let's say
the database has been seeded with a row that has id="unique-Identity" and another row has
an id="Unique-identity".  If the row is defined as "ID VARCHAR(255) PRIMARY KEY" then "unique-Identity"
is distinct from "Unique-identity" because of the differences in case.  In the above example,
if @Factory had worked, both would be presented as "UNIQUE-IDENTITY" -- there would be no
way to distinguish the rows based on the identity values presented by OpenJPA due to the transformation.

Obviously this is an extreme example (the problems are very obvious in this case), but it
does illustrate that there is more then enough rope for a person to hang themselves with.
> Should @Factory methods fire on Entity Identity fields?
> -------------------------------------------------------
>                 Key: OPENJPA-2109
>                 URL:
>             Project: OpenJPA
>          Issue Type: Question
>          Components: kernel
>            Reporter: Jody Grassel
>            Priority: Minor
> Question for the OpenJPA community.  Recently I had made an observation with the following
> @Entity                                                                 
> public class JAGExternEntity {                                          
>     @Id                                                                 
>     @Externalizer("JAGExternEntity.toLowercaseString")                  
>     @Factory("JAGExternEntity.toUppercaseString")                       
>     private String id;                                                  
>     @Externalizer("JAGExternEntity.toLowercaseString")                  
>     @Factory("JAGExternEntity.toUppercaseString")                       
>     private String extString;                                           
> ...                                                                     
>     (Standard default constructor, getter and setter methods)           
> ...                                                                     
>    public String toString() {                                           
>         return "JAGExternEntity [id=" + id + ", extString=" + extString + "]";      
>     }                                                                   
>     public static String toLowercaseString(String str) {                
>         return str.toLowerCase();                                       
>     }                                                                   
>     public static String toUppercaseString(String str) {                
>         return str.toUpperCase();                                       
>     }                                                                   
> }                                                                       
> Test Code (JUnit):                                                      
>     public void test000() throws Exception {                            
>         JAGExternEntity jee = new JAGExternEntity();                    
>         jee.setId("SomeIdentity");                                      
>         jee.setExtString("Some External String.");                      
>         System.out.println("Pre Persist: " + jee);                      
>         em.getTransaction().begin();                                    
>         em.persist(jee);                                                
>         System.out.println("Post Persist: " + jee);                     
>         em.getTransaction().commit();                                   
>         System.out.println("Post Commit: " + jee);                      
>         em.clear();                                                     
>         em.getTransaction().begin();                                    
>         Query q = em.createQuery("SELECT e FROM JAGExternEntity e");    
>         List<JAGExternEntity> resultList = q.getResultList();           
>         for (JAGExternEntity find : resultList) {                       
>             System.out.println("Query Result: " + find);                
>             em.remove(find);                                            
>         }                                                               
>         em.getTransaction().commit();                                   
>     }                                                                   
> And the test output:                                                    
> 517  jag-test  INFO   [main] openjpa.Runtime - OpenJPA dynamically loaded a validation
> 534  jag-test  INFO   [main] openjpa.Runtime - Starting OpenJPA 2.1.2-SNAPSHOT      
> 576  jag-test  INFO   [main] openjpa.jdbc.JDBC - Using dictionary class org.apache.openjpa.jdbc.sql.DerbyDictionary".
> Pre Persist: JAGExternEntity [id=SomeIdentity, extString=Some External String.]     
> Post Persist: JAGExternEntity [id=SomeIdentity, extString=Some External String.]    
> Post Commit: JAGExternEntity [id=SomeIdentity, extString=Some External String.]     
> Query Result: JAGExternEntity [id=someidentity, extString=SOME EXTERNAL STRING.]  
> What the above demonstrates is that @Externalizers will fire for all persistent fields,
including identity fields, but @Factories will only fire for non-identity persistent fields.
 This creates a one-way transformation scenario, where externalized values cannot be reversed
back for identity fields.  The OpenJPA documentation doesn't contain any text forbidding the
use of @Externalizer or @Factory on identity fields (except for embeddable ids, which was
the only noted exception.)
> I would like to hear the opinions of the community on this behavior.  Is it a mistake
that @Externalizer is allowed to fire on identity fields, but not @Factory.  Or is it a mistake
to allow @Externalizer to be allowed to be used by the identity field in the first place?
 Should any kind of transformation on identity fields even be allowed, because of the data
integrity/security issues that could arise from it?

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:!default.jspa
For more information on JIRA, see:


View raw message