CNemo7539
07-05-2007, 11:18 PM
Hello friends!
I have domain object and work with AdoTemplate. Reading was a breaze!
Now I need to persist changed object back to the database.
My domain object is a lot of collections. What will be the best approach to save such object? How can I map from object to commands?
Any hints will be appreciated!
Mark Pollack
07-06-2007, 02:50 AM
Hi,
Using AdoTemplate you could use one of the ExecuteNonQuery methods (http://www.springframework.net/doc-1.1-M1/sdk/2.0/html/Spring.Data~Spring.Data.ICommonAdoOperations~Execu teNonQuery.html). The most appropriate in this case is either one that takes ICommandSetter or the IDbParameters collection as a parameter. You will have to write the reverse mapping you did with RowMapper, that is getting domain object properties into parameter values. There are a few classes that can help with that, i.e. IDbParametersBuilder (http://www.springframework.net/doc-latest/reference/html/ado.html#d0e10480), which will let you write code like this
IDbParametersBuilder builder = CreateDbParametersBuilder();
builder.Create().Name("Country").Type(DbType.String).Size(15).Value(domainObject. Country);
builder.Create().Name("City").Type(DbType.String).Size(15).Value(domainObject. City);
IDbParameters parameters = builder.GetParameters();
and then pass parameters into ExecuteNonQuery of AdoTemplate. If you implement the ICommandSetter interface you can encapsulate that mapping logic in a single class. Since you have many collections in your domain object you could create a ICommandSetter implementation for each type of object in your collection and then in a top level DAO method, figure out which parts of the object graph you want to persist, and iterate though multiple calls to ExecuteNonQuery with appropriate ICommandSetter implementations.
Abstracting this approach a bit more, if you have the case where your object properties have the same name as your db columns then you could write some general purpose implementation of ICommandSetter that would encapsulate much of this boilerplate code using reflection. Using Spring's DynamicReflection API (http://www.springframework.net/doc-1.1-M1/sdk/2.0/html/Spring.Core~Spring.Util.DynamicReflection_namespac e.html), you wouldn't have a big performance hit.
Another abstraction would be to build upon the spring expression evaluation engine (SpEL (http://www.springframework.net/doc-latest/reference/html/expressions.html)) to externalize this boilerplate code, more of a mapping file approach. With a custom schema this could be
<statement name=insertPlace"
sql="INSERT INTO Place (Country, City) VALUES (@Country, @City)">
<binding type="MyDomainObject, MyAssembly">
<bind param="Name("Country").Type(DbType.String).Size(15)" property="Country"/>
<bind param="Name("City").Type(DbType.String).Size(15)" property="City.ShortName"/>
<binding/>
<statement>
Where you specify the SQL with property placeholders, then an collection of SpEL expression fragments to map/bind the object to the paramter. Each entry would specify what parameter type to create, then the SpEL expression that will be applied to a specific instance of the domain object.
You may want to consider using iBatis.NET. (http://ibatis.apache.org/) We haven't integrated our tx mgmt stuff with them yet though.
Food for thought...hope this helps.
Cheers,
Mark
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.