Alexey, What if we create a thin wrapper around PortableBuilder that implements IgniteObject? Since PortableBuilder already has getField() method, you only need to delegate to a builder in this wrapper. Then we can invoke the interface Dmitriy suggested, obtain hashCode and set it back to the builder.
In pseudo-code: PortableBuilder bld = getBuilder(); populateFromResultSet(bld); IgniteObject bldView = new BuilderIgniteObjectView(bld); int hashCode = hashBuilder.hashCode(bldView); bld.hashCode(hashCode); bld.build(); Thoughts? 2015-10-29 16:34 GMT+03:00 Alexey Kuznetsov <[email protected]>: > Dmitriy, > > > How about adding JdbcTypeHasher interface, which will look like this: > > interface JdbcTypeHasher { > > public int hashCode(IgniteObject o, Collection<String> fields); > >} > > User should be optionally set this interface at the JdbcType level. If > not > > set, then we use our default implementation. > > Will this work? > > First I thought it will work, but when I started to implement hasher > support I faced several problems: > 1) IgniteObject/PortableObject is actually immutable, so setting hashcode > for already constructed object looks dirty (set several bytes in array at > certain offset). > 2) It is not very efficient from implementation point of jdbc pojo store > (on more cycle over object fields with not very efficient access by name) > > So, I came to this solution: > > // Hash builder. > public interface JdbcTypeHashBuilder { > // Calculate hash code for specified value and field name. > public int toHash(Object val, String typeName, String fieldName); > > // Calculated hash code. > public int hash(); > } > > // Default implementation of JdbcTypeHashBuilder. User could implement its > own if needed. > public class JdbcTypeDefaultHashBuilder implements JdbcTypeHashBuilder { > private int hash = 0; > > @Override public int toHash(Object val, String typeName, String > fieldName) { > hash = 31 * hash + (val != null ? val.hashCode() : 0); > > return hash; > } > > @Override public int hash() { > return hash; > } > } > > // Factory for creating default hash builder: > public class JdbcTypeDefaultHashBuilderFactory implements > Factory<JdbcTypeHashBuilder> { > private static final long serialVersionUID = 0L; > > /** Instance of factory for reuse. */ > public final static JdbcTypeDefaultHashBuilderFactory INSTANCE = new > JdbcTypeDefaultHashBuilderFactory(); > > @Override public JdbcTypeHashBuilder create() { > return new JdbcTypeDefaultHashBuilder(); > } > } > > And I add factory to CacheJdbcPojoStoreConfiguration { > .... > private Factory<JdbcTypeHashBuilder> hashBuilderFactory = > JdbcTypeDefaultHashBuilderFactory.INSTANCE; > } > > Now I could build PortableObject and calculate its hash at the same time: > ... > portableBuilder = ... > > hashBuilder = factory.create(); > > for (dbField: dbFields) { > Object val = dbField.getValue(); > > portableBuilder.setField(dbField.getJavaName(), val) ; > hashBuilder.toHash(val, typeName, dbField.getJavaName()); > } > > return portableBuilder.hashCode(hashBuilder.hash()).build(); > > Thoughts? > > -- > Alexey Kuznetsov > GridGain Systems > www.gridgain.com >
