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 >= #fromDate#
</isNotNull>
<isNotNull property="toDate" prepend="and">
t.endDate <= #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# < (select sum(a.hours) from activity a where a.timesheetId
= t.timesheetId)
</isNotEmpty>
<isNotEmpty property="maxHours" prepend="and">
#maxHours# > (select sum(a.hours) from activity a where a.timesheetId
= t.timesheetId)
</isNotEmpty>
<isNotEmpty property="wageTypes" prepend="and">
0 < (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
>