Thanks, Dmitriy. I think your solution is more straightforward, no need to create wrappers.
Will implement this way. On Fri, Oct 30, 2015 at 6:00 AM, Dmitriy Setrakyan <[email protected]> wrote: > I am not sure I like this. We now require creation of some sort of > BuilderIgniteObjectView, which looks a bit over the top for me. > > How about using the hasher to calculate the hash-code and setting it into > the builder manually in your implementation? To my knowledge, builder > allows you to get individual field values, so you can get all the values > required to calculate the hash value: > > For example, here is what a hasher can look like: > > —————- > interface JdbcTypeHasher { > int hashCode(Collection<?> values); > } > —————- > > Then, somewhere in your code, you will set the hash-code on the builder > yourself: > > ————— > IgniteObjectBuilder builder = …; // initialize > > Collection<?> c = new ArrayList<>(); > > for (each field required for hash) { > c.add(builder.getField(name)); > } > > int hash = hasher.hashCode(c); > > builder.hashCode(hash); // Set hash-code on the builder. > —————— > > Thoughts? > > D. > > On Thu, Oct 29, 2015 at 7:23 AM, Alexey Kuznetsov <[email protected] > > > wrote: > > > Alexey, > > > > I like this very much, this almost solve my problems and I do not need > any > > fabrics! > > > > Thanks! > > > > On Thu, Oct 29, 2015 at 9:19 PM, Alexey Goncharuk < > > [email protected]> wrote: > > > > > 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 > > > > > > > > > > > > > > > -- > > Alexey Kuznetsov > > GridGain Systems > > www.gridgain.com > > > -- Alexey Kuznetsov GridGain Systems www.gridgain.com
