I'm not really sure why I don't like annotations... just seems to add more noise for my overworked brain to sift through, I suppose. I actually love @Override -- has saved me some frustration a few times already -- and there are some other annotations that are useful and not too instrusive.

However, I'm with Gwyn on this... The last thing I want to put in my java code 
is this:

<select id="getEmployeesByCriteria" parameterClass="map" resultClass="foo.bar.something.domain.EmployeeApprovalBean">
                select e.employeeId, pd.personnelNumber,
                RTRIM(pd.FirstName) as firstName,
                RTRIM(pd.MiddleName) as middleName,
                RTRIM(pd.LastName) as lastName,
                sl.statusDescription,
        t.timesheetId,
        t.startDate as timesheetStartDate,
        t.endDate as timesheetEndDate
        from PersonalData pd
                join Employee e
                        on pd.personnelNumber = e.personnelNumber
        join Timesheet t
                on e.employeeId = t.employeeId
        join StatusLut sl
                on t.statusId = sl.statusId
                <isNotEmpty property="approverIncluded">
        join supervisorGroup sg
            on sg.supervisorGroupId = e.supervisorGroupId
        join employee e2
            on sg.employeeId = e2.employeeId
        join PersonalData pd2
            on pd2.personnelNumber = e2.personnelNumber
        </isNotEmpty>
                <dynamic prepend="where">
                        <isNotNull property="fromDate" prepend="and">
                                t.startDate &gt;= #fromDate#
                        </isNotNull>
                        <isNotNull property="toDate" prepend="and">
                                t.endDate &lt;= #toDate#
                        </isNotNull>
                        <isNotEmpty property="firstName" prepend="and">
                                pd.firstName like #firstName# + '%'
                        </isNotEmpty>
                        <isNotEmpty property="middleName" prepend="and">
                                pd.middleName like #middleName# + '%'
                        </isNotEmpty>
                        <isNotEmpty property="lastName" prepend="and">
                                pd.lastName like #lastName# + '%'
                        </isNotEmpty>
                        <isNotEmpty property="personnelNumber" prepend="and">
                                pd.personnelNumber = #personnelNumber#
                        </isNotEmpty>
                        <isNotEmpty property="orgCode" prepend="and">
                                pd.organizationCode = #orgCode#
                        </isNotEmpty>
                        <isNotEmpty property="employeeTypes" prepend="and">
                pd.EmployeeSubGroup in (
                <iterate property="employeeTypes" conjunction="," close=")">
                    #employeeTypes[]#
                </iterate>
            </isNotEmpty>
            <isNotEmpty property="bargainingUnits" prepend="and">
                pd.BargainingUnitId in (
                <iterate property="bargainingUnits" conjunction="," close=")">
                    #bargainingUnits[]#
                </iterate>
            </isNotEmpty>
                        <isNotEmpty property="workSchedule" prepend="and">
                pd.workScheduleCode = #workSchedule#
            </isNotEmpty>
            <isNotEmpty property="minHours" prepend="and">
#minHours# &lt; (select sum(a.hours) from activity a where a.timesheetId = t.timesheetId)
            </isNotEmpty>
            <isNotEmpty property="maxHours" prepend="and">
#maxHours# &gt; (select sum(a.hours) from activity a where a.timesheetId = t.timesheetId)
            </isNotEmpty>
            <isNotEmpty property="wageTypes" prepend="and">
                0 &lt; (select count(a.activityId) from activity a, 
activityGroup ag
                                    where a.timesheetId = t.timesheetId
                                    and a.activityGroupId = ag.activityGroupId
                                    and ag.wageTypeId in (
                                    <iterate property="wageTypes" 
conjunction=",">
                                    #wageTypes[]#
                                    </iterate> )
                        )
            </isNotEmpty>
            <isNotEmpty property="approverIncluded">
                <isNotEmpty property="approverFirstName" prepend="and">
                pd2.FirstName like #approverFirstName# + '%'
                </isNotEmpty>
                <isNotEmpty property="approverLastName" prepend="and">
                pd2.LastName like #approverLastName# + '%'
                </isNotEmpty>
                <isNotEmpty property="approverPersonnelNumber" prepend="and">
                pd2.PersonnelNumber = #approverPersonnelNumber#
                </isNotEmpty>
            </isNotEmpty>
            <isNotEmpty property="statuses" prepend="and">
                t.statusId in (
                <iterate property="statuses" conjunction="," close=")">
                    #statuses[]#
                </iterate>
            </isNotEmpty>
            <isNotEmpty property="noApprover" prepend="and">
                e.supervisorGroupId is null
            </isNotEmpty>
                </dynamic>
        order by lastName
        </select>


Ok, that's a monster search query with a lot of dynamic stuff, so maybe it's not a candidate for an annotation (the result gets put in a bean though, so it could).

But I think Larry's point is very valid. Books and tutorials just love to whip out stultified examples for stuff like this... "select * from foo where blah blah". But life is almost never that simple. Well, at least not in the world of consulting for State government.

I also think that avoiding recompilation is never the reason for externalizing things from code (configs, sql, etc.). That's often talked about and it can be nice to be able to make a change to a config file and just reload the app (though in practice, the app is always deployed as a .war so we always recompile and redeploy the whole thing anyway), but for me the most important reason is just keeping the code clean and as narrowly focused as possible. That's the IOC ideal in my mind.

b

Clinton Begin wrote:
I've already started some preliminary design work for iBATIS 3, and it does include both annotation and XML support.

I have to get it on the wiki...

But anyway, I agree about the one-liner thing...but that could be easily fixed with very simple multiline support in the compiler. In both the C# version and the Ruby version you can do multiline string, for example, in C#:

@"SELECT
        FIRST_NAME
        LAST_NAME
        BIRTH_DATE
     FROM PERSON
     WHERE LAST_NAME LIKE @lastName
     AND DECEASED = false"

Super nice. So annotations can be great, I actually prefer them to XML, as I rarely need to change my SQL without recompiling and running my tests anyway. But I can understand others have different situations --supporting both is fairly straight forward. Luckily, Sun made annotations such just as bad as XML, so it's an easier translation in Java.

The C# Attribute support will be harder to keep consistent with the XML, because there are so many improvements one can make using ordinal parameters and simple things like supporting multiple attributes of the same name clean up the code significantly.

Cheers,
Clinton


On 8/5/06, *Larry Meadors* <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>> wrote:

    Heh, my bet is that Sun delivers enough to make iBATIS easier to
    write, but still manages to overcomplexificate it enough to make
    people still want to use something else.

    It is cool to see things like DataSet<Employee> coming from the API,
    but unless DataSet extends List, I do not want that anywhere but in my
    DAO layer, just like I do not want a ResultSet anywhere but in my DAO
    layer. If it does, great! That is a huge advancement.

    While stuff like @Select("SELECT * FROM Employee WHERE status = 'A'")
    looks very attractive, and simple crud accounts for probably 35-50% of
    the statements I use, only about 2% of the SQL I write beyond CRUD
    fits into the 1-liner category.

    The rest of the SQL statements are those 80-100 line select statements
    with dynamic elements...and as much as I like the StringBuilder
    class...I still prefer <dynamic> elements to java code. ;-)

    So...top question on my list...can/should we use this for iBATIS3? ;-)

    Larry

    On 8/4/06, Clinton Begin <[EMAIL PROTECTED]
    <mailto:[EMAIL PROTECTED]>> wrote:
     > Hi all,
     >
     > I just picked this up from InfoQ.  What do you think?
     >
     >
     > =====================
     > Blogger Patrick Lightbody noted "I could see JDBC 4.0 replacing
    my need for
     > iBatis" after reading another blog post on JDBC 4.0
    functionality. JDBC 4.0
     > includes basic O/R mapper functionality that eases the repetitive
    task of
     > copying ResultSet data into objects. It does not handle
    inheritance or table
     > relations however.
     > =====================
     >
     >
     > http://www.infoq.com/news/Easier-Database-Development-JDBC
     >
     > Patrick's a good guy and a respected developer.  I appreciate his
    opinion.
     > Obviously, this is only useful for people running JDK 5 or
    possibly only JDK
     > 6.  And of course, Annotation support would be an almost
    brainless effort to
     > implement for iBATIS.  Your thoughts?
     >
     > Clinton
     >


Reply via email to