ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Clinton Begin <clinton.be...@gmail.com>
Subject Re: Unconstrained signature interface mappers for ibatis 3
Date Sun, 30 Aug 2009 14:44:45 GMT
I love the idea, and I think we even have it on the wiki...

However, I attempted the implementation and could not land on a design that
was nice.  The biggest problem is that Java lacks introspection on method
parameter names.  What I would really love is:

@Select("select * from employee where first_name = #{firstName}" and
last_name = #{lastName})
Employee findEmployeeLike(String firstName, String lastName);

That would truly be awesome (of course complex types would work too).   This
is perfectly possible in C#, where I can get the names of the parameters.
However in Java, there is no such means.  So that leaves us with pretty much
two options:

1) Ordinal -- I don't like this, because it's akin to the ordinal ? params
in standard JDBC prepared statements. By supporting multiple params, the
value of the feature should increase with more params, but here, adding more
params makes the SQL less readable and harder to change later (i.e.
refactoring to add a new param in the middle of the method signature).
Doesn't bode well for this feature.

@Select("select * from employee where first_name = #{1} and last_name =
#{2})
Employee findEmployeeLike(String firstName, String lastName);

2) Annotations -- We could add annotations to the parameters... this just
ended up looking silly.

@Select("select * from employee where first_name = #{firstName} and
last_name = #{lastName})
Employee findEmployeeLike(@Param("firstName") String firstName,
@Param("lastName") String lastName);

An alternative was to use a single annotation...

@Select("select * from employee where first_name = #{firstName} and
last_name = #{lastName})
@Params("firstName","lastName")
Employee findEmployeeLike(String firstName, String lastName);

But that kind of repetition makes me sad.  :-(

At the end of the day I gave up, because all of these were so repetitive,
hard to maintain (due to the alignment and ordinal positioning) and don't
read well.

I really wish Java made this easier.  One thought I had to submit to the JCP
was to add introspection on parameter names by having the compiler
automatically create annotations for the parameter names.

For example, given the method:

Employee findEmployeeLike(String firstName, String lastName);

The compiler would automatically create @MethodParameterName annotation (or
something similar) for each parameter.  Then I could either use the regular
annotation API to fetch them, or a cleaner API like String[]
method.getParameterNames().

But I decided by the time that made it into the framework we'd be at JDK 9
and who knows where iBATIS would be.  :-)

I'm open to more ideas... but the goals have to be:

1) No repetition
2) No ordinal positioning
3) Descriptive SQL
4) Easy to maintain

Thoughts?

Cheers,
Clinton

On Sun, Aug 30, 2009 at 3:30 AM, <carlosjosepita@gmail.com> wrote:

> > It just requires a trivial modification in MapperMethod and a simple
> > mechanism to access positional parameters to get it working. For
> > example, MapperMethod could create a Map and put the first argument
> > under the key "first", the second one under "second", etc. That is,
> > positional access "by name". Of course, in case the number of
> > arguments were only one, the usual mechanism would follow.
>
>
> Another possibility is to take advantage of java 5 varargs feature and
> allow SqlSession methods to accept multiple parameters with Object...:
>
> Object selectOne(String statement, Object... parameters);
>
> (Of course, the currently overloaded selectOne:
>
>     Object selectOne(String statement);
>     Object selectOne(String statement, Object parameter);
>
> would be merged into the single method above).
>
> As before, when length > 1 the varargs will be automatically stored into
> a Map under "positional" keys like "arg1", "arg2", etc (I'm not sure if
> the shorter "1", "2", etc are compatible with javabeans as in "bean.1",
> "bean.2").
>
> This way MapperMethod will just forward its Object[] args to the SqlSession
> method selectOne, selectList, etc.
>
> Notice that any change that I have proposed is absolutely backwards
> compatible:
>
> 1) Object... still can take single arguments.
> 2) If just one argument is given the { "arg1": arg1, "arg2": arg2, ...}
> map will not be created at all.
> 3) Sql expecting one argument won't need to be modified.
>
> However, SqlSession won't compile with java 1.4 or older due to the
> introduction of varargs. I don't know if this is a concern for ibatis 3.
> In that case, the proposal of my previous post doesn't suffer the same
> inconvenience, althought it is more limited.
>
> I would like to hear your opinion about it.
>
> Best regards
> --
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-java-unsubscribe@ibatis.apache.org
> For additional commands, e-mail: user-java-help@ibatis.apache.org
>
>

Mime
View raw message