You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Milosz Tylenda (JIRA)" <ji...@apache.org> on 2010/06/25 09:17:49 UTC

[jira] Commented: (OPENJPA-1687) @Strategy and @ElementStrategy handling resets/obstructs SQL type set in the custom handler map() call.

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

Milosz Tylenda commented on OPENJPA-1687:
-----------------------------------------

Krzysztof has confirmed in private mail that the following mapping gives what is desired - schema tool creates a column of type float8[] and persisting and reading primitive arrays works correctly.

1. Modify the Handler like this:

public class PostgresJPAArrayHandler
    extends AbstractValueHandler {

 public PostgresJPAArrayHandler()
 {
 }
 
/**
* Serialization ID
*/
private static final long serialVersionUID = 1L;
private static final PostgresJPAArrayHandler _instance =
            new PostgresJPAArrayHandler();

    /**
     * Singleton instance.
     */
    public static PostgresJPAArrayHandler getInstance() {
        return _instance;
    }

    public Column[] map(ValueMapping vm, String name, ColumnIO io,
        boolean adapt) {
        Column col = new Column();
        col.setName(name);         
        col.setTypeName("float8[]");    
        col.setJavaType(JavaSQLTypes.SQL_ARRAY);
        return new Column[]{ col };   

    }

    public Object toDataStoreValue(ValueMapping vm, Object val,
        JDBCStore store) {

   //this has to be array of some integer or double for now
   if (val instanceof double[]) {
try {
Connection unwrapped = ((DelegatingConnection) store.getConnection()).getInnermostDelegate();
Array darr = unwrapped.createArrayOf("float8", (Object[]) ( ArrayUtils.toObject((double[])val)));
return darr;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
       return  null;
}
    /** Convert from DB rep into OM representation */
    public Object toObjectValue(ValueMapping vm, Object val) {
        if (val == null)
            return null;
        try {
return ArrayUtils.toPrimitive((Double[])((Array)val).getArray());
} catch (SQLException e) {
// TODO Auto-generated catch block
return null;
}
}   
}


2. Annotate the field:

   @PersistentCollection
   @Strategy("milosz.pgsql.handler.PostgresJPAArrayHandler")
   private double[] tabka;

3. Provide an extended PostgresDictionary with this overridden method:

   public void setBlobObject(PreparedStatement stmnt, int idx, Object val,
       Column col, JDBCStore store)
       throws SQLException {
       if (col.getTypeName().equals("float8[]")) {
           setArray(stmnt, idx, (Array) val, col);
           return;
       }
       setBytes(stmnt, idx, serialize(val, store), col);
   }



> @Strategy and @ElementStrategy handling resets/obstructs SQL type set in the custom handler map() call.
> -------------------------------------------------------------------------------------------------------
>
>                 Key: OPENJPA-1687
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1687
>             Project: OpenJPA
>          Issue Type: Bug
>    Affects Versions: 2.0.0
>         Environment: OS X, Linux
>            Reporter: Krzysztof
>            Assignee: Milosz Tylenda
>
> OpenJPA advertises itself as an expandable framework and provides @Strategy (and undocumented) @ElementStrategy annotations to create custom java<->SQL mappings.
> I would like to create support for already existing JDBC4 standard mapping of primitive arrays in i.e. Postgres:
> java double[] <-> SQL float8[]
> Unfortunately it is not possible using @Strategy as enhancer blindly checks if the field is a collection/array and refuses to do anything with it.
> In the case like this a field should not be delegated to an external table but simply embedded - same way LOBs are, with different toDataStoreValue/toObjectValue pair as provided in the strategy implementation below..
> If we use @ElementStrategy however, i.e.:
> <class>
>  @PersistentCollection
>     @ElementStrategy("gaia.cu7.dal.PostgresJPAArrayHandler")
>     @ElementColumns({
>         @ElementColumn(name="TDOUBLE")
>     })
>  private double tdouble[];
> </class>
> then enhancer accepts it. Schema synchronisation creates wrong DDL suppressing given SQL type and mapping it to SQL keyword ARRAY in the external table.
> Does this rather simple requirement is not covered by openJPA? 
> public class PostgresJPAArrayHandler
>     extends AbstractValueHandler {
>  public PostgresJPAArrayHandler()
>  {
>  
>  }
>      /**
> 	 * Serialization ID
> 	 */
> 	private static final long serialVersionUID = 1L;
> 	private static final PostgresJPAArrayHandler _instance =
>             new PostgresJPAArrayHandler();
>     /**
>      * Singleton instance.
>      */
>     public static PostgresJPAArrayHandler getInstance() {
>         return _instance;
>     }
>     public Column[] map(ValueMapping vm, String name, ColumnIO io,
>         boolean adapt) {
>         Column col = new Column();
>         col.setName(name);        
>         col.setType(JavaSQLTypes.SQL_ARRAY);
>         col.setTypeName("float8[]");    //////<<<--------------------- this gets reset in mergeField or whereabouts
>  
>         return new Column[]{ col };
>     }
>     public Object toDataStoreValue(ValueMapping vm, Object val,
>         JDBCStore store) {
>     	//this has to be array of some integer or double for now
>     	if (val instanceof double[]) {
>     		
> 			try {
> 				Array darr = store.getConnection().createArrayOf("double", (Object[]) ( ArrayUtils.toObject((double[])val)));
> 				return darr;
> 			} catch (SQLException e) {
> 				// TODO Auto-generated catch block
> 				e.printStackTrace();
> 			}
> 			
> 		}
>         return  null;
>     }
>     /** Convert from DB rep into OM representation */
>     public Object toObjectValue(ValueMapping vm, Object val) {
>         if (val == null)
>             return null;
>         return ArrayUtils.toPrimitive((Double[])val);
>     }
>     
> }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.