- 浏览: 453106 次
最新评论
-
carlos23:
我想知道用WriterLogger后,里面的writer在外面 ...
论面向组合子程序设计方法 之 燃烧的荆棘 -
marsyoung:
讲的什么。。没看懂。例子太抽象。。
论面向组合子程序设计方法 之 创世纪 -
wanghhao:
优雅的方式!
论面向组合子程序设计方法 之 微步毂纹生 -
ykdsg:
有源码吗?
论面向组合子程序设计方法 之 monad -
咱不怕:
如果在一个函数中多次使用到这个不变temp对象,按照Marti ...
关于 Replace Temp With Query
公司的一个大系统的持久层一直是直接使用jdbc。在jdbc的基础上,又自制了一个简陋的cache。
每个持久功能的实现都比较类似,大致相当于这样:
当然,各个功能的实现不完全一样,有的有事务,有的没有;有的忘了关闭statement,有的忘了checkIn connection;有的在出现Error的时候忘了rollback。等等等等。
dao层的代码就是调用这些不同的jdbc代码,然后再包上一层HashMap做cache:
当然,还要自己实现cloneAccount()。
所有对Account, Contribution, Plan之类的cache代码也类似。
后来鉴于偶尔出现资源泄漏问题,一个程序员写了一个jdbc模板,长成这个样子:
然后上面的代码可以简化为仅仅重载这四个抽象函数:
getStatement负责取得某个特定的sql statement;populateStatement负责填充参数;processResult负责把ResultSet转换成domain object;isTransactional制定是否使用事务。
介绍了这么多背景情况,希望你已经看到了,原来的直接jdbc方法是非常繁琐,容易出错,代码量大,而且重复很多。
这个PersisterCommand也有很多局限:
1。它只能处理一个connection一个statement,不能做batch。
2。它在Error出现的时候没有rollback。
3。子类仍然要针对jdbc api写一些有重复味道的代码。
4。代码不容易单元测试。因为ConnectionManager.checkOut()和ConnectionManager.checkIn()都是写死的。
另外,这个自制的cache也是一个重复代码的生产者。
针对这种情况,我本来想继续重构,弄出一个CacheManager和更灵活的jdbc模板。但是后来一想,倒还不如直接用ibatis来得好。毕竟ibatis已经是被业界广泛使用的工具,总比自己制造轮子强。而且,相比于hibernate,ibatis也有更贴近我们现在的模型和使用习惯的优势。
我的一个同事(公司的元老),开始是对ibatis很感兴趣的。
可惜的是,当我完成了ibatis的集成,他试用了一下之后就改变了主意。这个同事在项目组甚至整个公司说话都是很有分量的,不说服他,推广ibatis就面临夭折的可能。
我的ibatis的集成长成这个样子:
这样,除非用户代码调用openSession(),其它的函数都自动处理了Session的关闭。事务处理用一个boolean参数来控制也相当简单。
上面的那么多jdbc代码和cache代码最终就可以直接变成:
那么同事对这个东西的意见在哪里呢?
1。他和另外一个同事为调试一个使用了ibatis的程序bug花了一天时间。后来把ibatis删掉,直接用jdbc就修好了。
当时我在休假,回来后一看,这个bug首先是一个stored proc的bug。他们花很多时间在ibatis里面找问题其实都是瞎耽误工夫;其次,在他们到处找ibatis的问题的时候,注释掉了两行关键代码,后来忘了放回来,所以才发生stored proc修好后,ibatis代码还是不工作,直到换了jdbc才修好。
虽然我解释了原因,同事坚持认为ibatis过于复杂。如果它花了他这么长时间来debug,别人也有可能因为种种原因花很多时间来debug别的问题。
2。ibatis只支持一个参数。这个我也解释了,你可以用java bean或者Map。可是同事认为这也是ibatis的学习曲线问题。如果采用,就要求大家都去学ibatis doc才行。
3。同事原来期待的是象Active Record那样的革命性的提高和简化。象ibatis这样还是要进行手工mapping的,对他来说就是没什么太大意义。他不觉得在java里面做这个mapping有什么不好。(我想,也许Hibernate对他更有吸引力。不过把这个系统转换为Hibernate这工作量可大多了)
4。当我说ibatis可以节省很多资源管理的重复代码时,同事说他可以用PersisterCommand。我说PersisterCommand的这些局限性的时候,他说,他不在乎。大不了直接写jdbc。
5。一致性问题。如果同时用jdbc和ibatis,大家就要学两个东西,造成混淆。而如果要把所有东西都换成ibatis,工作量是一个方面,所有的人都要学习ibatis这个代价也是很大的。
6。同事认为cache的那点重复代码无所谓。即使有一些降低cache hit ratio的bug也不是什么大不了的。
最后无法达成统一意见。因为你说什么优点的时候,他只要一句“我不在乎”你就无话可说了。
在这些论点里面,我也认可ibatis的学习曲线和一致性问题。可是,总不能就永远任由这个持久层代码这么滥下去吧?在java这个领域里,我几乎完全相信不可能出现Active Record等价的东西的。而无论Hibernate还是jpa,只怕都是有不下于ibatis的学习曲线和更高的从遗留系统移植的代价吧?
越来越感觉自己不是一个合格的architect。因为我缺乏说服人的能力。
你怎么看这个问题呢?
他这个还不如我的那个。他的这个实现没有处理Error的情况。在Error出现的情况,不会回滚事务。
不管我的还是同事的这个都有若干个问题:
1。不支持cache。还要自己写cache,不如ibatis直接提供的cache支持方便。
2。不支持一个connection多个query或者命令。
既然想到了 何不搞个出来 这段话下面贴个附件带上你的demo 该有多漂亮 呵呵
我觉得你还是在从技术层面看问题,还是过于急迫地进入细节。
第一步,不预设任何方案,说服同事选择开源框架,而避免陷入自己开放又一个框架的泥潭;
第二步,你们一起选择一个合适的开源框架。
到底选择哪一个,等解决了第一步以后再说。如果ibatis真的是最适合你们的方案,我相信一旦你们进入第二步,在同事的参与下你们最终会选择ibatis。与其去推销自己的选择,不如引导他作出同样的选择。
ibatis允许配置DataSourceFactory。
我用dynamic proxy把所有的jdbc call都拦截了,这样调试起来其实更方便。
每个持久功能的实现都比较类似,大致相当于这样:
MyProprietaryConnection conn = ConnectionManager.checkOut(Database.DB_NAME); try { PreparedStatement stmt = conn.getPreparedStatement("some statement id, identifying a sql statement in an xml file"); stmt.setString(1, "param 1"); stmt.setInt(2, param2); ... try { ResultSet resultSet = stmt.executeQuery(); try{ while(resultSet.next()) { ... } } finally { resultSet.close(); } } finally { stmt.close(); } } finally { ConnectionManager.checkIn(conn); }
当然,各个功能的实现不完全一样,有的有事务,有的没有;有的忘了关闭statement,有的忘了checkIn connection;有的在出现Error的时候忘了rollback。等等等等。
dao层的代码就是调用这些不同的jdbc代码,然后再包上一层HashMap做cache:
Object cacheKey = ...; synchronized(cache) { Account acct = (Account)cache.get(cacheKey); if(acct == null) { acct = runJdbcForAccount(...); cache.put(cacheKey, acct); } return acct.cloneAccount(); }
当然,还要自己实现cloneAccount()。
所有对Account, Contribution, Plan之类的cache代码也类似。
后来鉴于偶尔出现资源泄漏问题,一个程序员写了一个jdbc模板,长成这个样子:
abstract class PersisterCommand { protected abstract void populateStatement(PreparedStatement stmt); protected abstract Object processResult(ResultSet resultSet); protected abstract boolean isTransactional(); protected abstract PreparedStatement getStatement(); public Object run() { MyProprietaryConnection conn = ConnectionManager.checkOut(Database.DB_NAME); try { PreparedStatement stmt = getStatement(); populateStatement(stmt); ... try { if(isTransactional()) { conn.startTransaction(); } ResultSet resultSet = stmt.executeQuery(); try{ Object result = processResult(resultSet); if(isTransactional()) { conn.commitTransaction(); } return result; } catch(Exception e){ if(isTransactional()) conn.rollbackTransaction(); throw e; } finally { resultSet.close(); } } finally { stmt.close(); } } finally { ConnectionManager.checkIn(conn); } } }
然后上面的代码可以简化为仅仅重载这四个抽象函数:
getStatement负责取得某个特定的sql statement;populateStatement负责填充参数;processResult负责把ResultSet转换成domain object;isTransactional制定是否使用事务。
介绍了这么多背景情况,希望你已经看到了,原来的直接jdbc方法是非常繁琐,容易出错,代码量大,而且重复很多。
这个PersisterCommand也有很多局限:
1。它只能处理一个connection一个statement,不能做batch。
2。它在Error出现的时候没有rollback。
3。子类仍然要针对jdbc api写一些有重复味道的代码。
4。代码不容易单元测试。因为ConnectionManager.checkOut()和ConnectionManager.checkIn()都是写死的。
另外,这个自制的cache也是一个重复代码的生产者。
针对这种情况,我本来想继续重构,弄出一个CacheManager和更灵活的jdbc模板。但是后来一想,倒还不如直接用ibatis来得好。毕竟ibatis已经是被业界广泛使用的工具,总比自己制造轮子强。而且,相比于hibernate,ibatis也有更贴近我们现在的模型和使用习惯的优势。
我的一个同事(公司的元老),开始是对ibatis很感兴趣的。
可惜的是,当我完成了ibatis的集成,他试用了一下之后就改变了主意。这个同事在项目组甚至整个公司说话都是很有分量的,不说服他,推广ibatis就面临夭折的可能。
我的ibatis的集成长成这个样子:
public interface Action { Object run(SqlMapSession session); } public class IbatisPersistence { public SqlMapSession openSession(); public Object queryForObject(String key); public List queryForList(String key); public int update(String key, boolean useTransaction); public int delete(String key, boolean useTransaction); public int update(String key); public int delete(String key); public Object run(Action action); }
这样,除非用户代码调用openSession(),其它的函数都自动处理了Session的关闭。事务处理用一个boolean参数来控制也相当简单。
上面的那么多jdbc代码和cache代码最终就可以直接变成:
Accunt acct = persistence.queryForObject("getAccountById", accountId);
那么同事对这个东西的意见在哪里呢?
1。他和另外一个同事为调试一个使用了ibatis的程序bug花了一天时间。后来把ibatis删掉,直接用jdbc就修好了。
当时我在休假,回来后一看,这个bug首先是一个stored proc的bug。他们花很多时间在ibatis里面找问题其实都是瞎耽误工夫;其次,在他们到处找ibatis的问题的时候,注释掉了两行关键代码,后来忘了放回来,所以才发生stored proc修好后,ibatis代码还是不工作,直到换了jdbc才修好。
虽然我解释了原因,同事坚持认为ibatis过于复杂。如果它花了他这么长时间来debug,别人也有可能因为种种原因花很多时间来debug别的问题。
2。ibatis只支持一个参数。这个我也解释了,你可以用java bean或者Map。可是同事认为这也是ibatis的学习曲线问题。如果采用,就要求大家都去学ibatis doc才行。
3。同事原来期待的是象Active Record那样的革命性的提高和简化。象ibatis这样还是要进行手工mapping的,对他来说就是没什么太大意义。他不觉得在java里面做这个mapping有什么不好。(我想,也许Hibernate对他更有吸引力。不过把这个系统转换为Hibernate这工作量可大多了)
4。当我说ibatis可以节省很多资源管理的重复代码时,同事说他可以用PersisterCommand。我说PersisterCommand的这些局限性的时候,他说,他不在乎。大不了直接写jdbc。
5。一致性问题。如果同时用jdbc和ibatis,大家就要学两个东西,造成混淆。而如果要把所有东西都换成ibatis,工作量是一个方面,所有的人都要学习ibatis这个代价也是很大的。
6。同事认为cache的那点重复代码无所谓。即使有一些降低cache hit ratio的bug也不是什么大不了的。
最后无法达成统一意见。因为你说什么优点的时候,他只要一句“我不在乎”你就无话可说了。
在这些论点里面,我也认可ibatis的学习曲线和一致性问题。可是,总不能就永远任由这个持久层代码这么滥下去吧?在java这个领域里,我几乎完全相信不可能出现Active Record等价的东西的。而无论Hibernate还是jpa,只怕都是有不下于ibatis的学习曲线和更高的从遗留系统移植的代价吧?
越来越感觉自己不是一个合格的architect。因为我缺乏说服人的能力。
你怎么看这个问题呢?
评论
57 楼
zagile
2007-08-16
原来的系统跑得好好的,需要很强的理由才能说服当官的决定替换。
56 楼
lszone
2007-08-15
ibatis麻烦?你用hibernate试试
55 楼
fixopen
2007-08-15
屁股决定脑袋。
因为自己的立场和利益,每个人都会坚持一些从别人看来不可理解的东西,都会时不时的担心一下这个新的外来者是不是会损害自己的利益。
最让你感觉到无能为力的是“我不care”,但这其实也是你最大的攻击点,问问他care什么?告诉他什么能帮助他更好的care这些东西。当然,一定不能忘了工程的投入产出这个最大的砝码。
因为自己的立场和利益,每个人都会坚持一些从别人看来不可理解的东西,都会时不时的担心一下这个新的外来者是不是会损害自己的利益。
最让你感觉到无能为力的是“我不care”,但这其实也是你最大的攻击点,问问他care什么?告诉他什么能帮助他更好的care这些东西。当然,一定不能忘了工程的投入产出这个最大的砝码。
54 楼
spiritfrog
2007-04-13
这根本就不是技术问题,都是人的问题,人家固执保守,不肯学习新东西,确实就很无奈。当architect没有他人的拥护看来也是不行的。
53 楼
抛出异常的爱
2007-02-26
jdbc 不是架构
ibatis是架构
要用什么就看哪个架构省力
如果要升级那就要看是否非要升级所有的文件
原有的有必要修改的代码也可以用重构的方式完成
由于jdbc可以离开架构而存在
所以没必要非把所有的代码都移到新的架构上面
ibatis是架构
要用什么就看哪个架构省力
如果要升级那就要看是否非要升级所有的文件
原有的有必要修改的代码也可以用重构的方式完成
由于jdbc可以离开架构而存在
所以没必要非把所有的代码都移到新的架构上面
52 楼
ajoo
2007-02-26
intolong 写道
ajoo不是写过jdbc template么?
http://www.iteye.com/topic/7068
和你同事那个差不多吧,一个继承,一个组合
http://www.iteye.com/topic/7068
和你同事那个差不多吧,一个继承,一个组合
他这个还不如我的那个。他的这个实现没有处理Error的情况。在Error出现的情况,不会回滚事务。
不管我的还是同事的这个都有若干个问题:
1。不支持cache。还要自己写cache,不如ibatis直接提供的cache支持方便。
2。不支持一个connection多个query或者命令。
51 楼
fuliang
2007-02-26
我以前做的一个对jdbc的封装(仿照Spring的实现,当然功能弱些,所以代码少很多,容易看)
以下是对jdbc进行了简单的封装:使用Template mothod模式和回调接口大大减少了对jdbc的低级操作。其中JdbcTemplate类提供了使用jdbc访问数据库的模板,提供了queryForObject和queryForList方法来分别获取查询到的对象和对象的聚集,execute方法来更新、插入、删除操作。提供了RowCallBackHandler接口,可以通过实现该接口来提供对查询一行的回调处理,使用PreparedStatementCallBack回调接口,来提供对PreparedStatement参数的设置,提供了ORMaping接口,通过实现该接口可以很容易实现关系数据库与domain对象的映射,并产生可重用的逻辑
以下是代码包含对JDBC的封装和Dao的实现:
以下是对jdbc进行了简单的封装:使用Template mothod模式和回调接口大大减少了对jdbc的低级操作。其中JdbcTemplate类提供了使用jdbc访问数据库的模板,提供了queryForObject和queryForList方法来分别获取查询到的对象和对象的聚集,execute方法来更新、插入、删除操作。提供了RowCallBackHandler接口,可以通过实现该接口来提供对查询一行的回调处理,使用PreparedStatementCallBack回调接口,来提供对PreparedStatement参数的设置,提供了ORMaping接口,通过实现该接口可以很容易实现关系数据库与domain对象的映射,并产生可重用的逻辑
以下是代码包含对JDBC的封装和Dao的实现:
package edu.jlu.fuliang.library.jdbc; import java.util.ArrayList; import java.util.List; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class JdbcTemplate { public List query(String sql,RowCallBackHandler handler){ Connection connection = JdbcUtils.createConnection(); PreparedStatement ps = JdbcUtils.createPreparedStatement(sql,connection); ResultSet rs = null; List list = new ArrayList(); try { rs = ps.executeQuery(); while(rs.next()){ list.add(handler.processRow(rs)); } } catch (SQLException e) { e.printStackTrace(); }finally{ JdbcUtils.closeStatement(ps); JdbcUtils.relaseConnection(connection); } return list; } public Object queryForObject(String sql,RowCallBackHandler handler){ Connection connection = JdbcUtils.createConnection(); PreparedStatement ps = JdbcUtils.createPreparedStatement(sql,connection); ResultSet rs = null; Object o = null; try { rs = ps.executeQuery(); rs.next(); o = handler.processRow(rs); } catch (SQLException e) { e.printStackTrace(); }finally{ JdbcUtils.closeStatement(ps); JdbcUtils.relaseConnection(connection); } return o; } public void executeUpdate(String sql,PreparedStatementCallBack pareparedStatementCallBack){ Connection connection = JdbcUtils.createConnection(); PreparedStatement ps = JdbcUtils.createPreparedStatement(sql,connection); try { pareparedStatementCallBack.doInStatement(ps); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally{ JdbcUtils.closeStatement(ps); JdbcUtils.relaseConnection(connection); } } } //回调接口RowCallBackHandler package edu.jlu.fuliang.library.jdbc; import java.sql.ResultSet; public interface RowCallBackHandler { public Object processRow(ResultSet rs); } ///回调接口PreparedStatementCallBack package edu.jlu.fuliang.library.jdbc; import java.sql.PreparedStatement; import java.sql.SQLException; public interface PreparedStatementCallBack { public void doInStatement(PreparedStatement stmt)throws SQLException; } //ORMaping接口 package edu.jlu.fuliang.library.jdbc; import java.sql.ResultSet; public interface ORMaping { public Object mapping(ResultSet rs,Object o); } //JdbcUtils.java package edu.jlu.fuliang.library.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; public class JdbcUtils { public static Connection createConnection(){//为了简单,进行了硬编码 String user = "root"; String passwd = "123456"; String url = "jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=gb2312"; Connection connection = null; try{ Class.forName("com.mysql.jdbc.Driver").newInstance(); connection = DriverManager.getConnection(url,user,passwd); } catch(Exception e){ e.printStackTrace(); } return connection; } public static PreparedStatement createPreparedStatement(String sql,Connection connection){ PreparedStatement stmt = null; try{ stmt = connection.prepareStatement(sql); }catch(Exception e){ e.printStackTrace(); } return stmt; } public static void closeStatement(Statement s){ try { s.close(); } catch (SQLException e) { e.printStackTrace(); } } public static void relaseConnection(Connection connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } //以下是数据访问对象: //BorrowerDao.java package edu.jlu.fuliang.library.dao; import edu.jlu.fuliang.library.domain.Borrower; public interface BorrowerDao { public Borrower queryByLastName(String lastName); public void updateBorrower(Borrower borrower); public void insertBorrower(Borrower borrower); public void deleteBorrowerByLastName(String lastName); } // BookDao.java package edu.jlu.fuliang.library.dao; import java.util.List; import edu.jlu.fuliang.library.domain.Book; public interface BookDao { public Book queryByTitle(String title); public List queryByAuthor(String author); public List queryByBorrowerLastName(String firstName); public void updateBook(Book book); public void insertBook(Book book); public void deleteBookByTile(String title); } // BorrowOrReturnDao.java package edu.jlu.fuliang.library.dao; public interface BorrowOrReturnDao { public void borrowBook(String borrowerLastName,String bookTile); public void returnBook(String borrowerLastName,String bookTile); } //抽象工厂: package edu.jlu.fuliang.library.dao; public interface DaoFactory { public BookDao createBookDao(); public BorrowerDao createBorrowerDao(); public BorrowOrReturnDao createBorrowOrReturnDao(); } //具体工厂: package edu.jlu.fuliang.library.dao; import edu.jlu.fuliang.library.dao.mysql.BookDaoImpl; import edu.jlu.fuliang.library.dao.mysql.BorrowerDaoImpl; public class MysqlDaoFactory implements DaoFactory{ public BookDao createBookDao() { return new BookDaoImpl(); } public BorrowerDao createBorrowerDao() { return new BorrowerDaoImpl(); } public BorrowOrReturnDao createBorrowOrReturnDao() { return new BorrowOrReturnDaoImpl(); } } //BookDao的具体实现: //BookDaoImpl.java package edu.jlu.fuliang.library.dao.mysql; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import edu.jlu.fuliang.library.dao.BookDao; import edu.jlu.fuliang.library.domain.Book; import edu.jlu.fuliang.library.jdbc.*; public class BookDaoImpl implements BookDao{ private JdbcTemplate jdbcTemplate = new JdbcTemplate(); public Book queryByTitle(String title) { String sql = "select * from book where title = "+title; return (Book)jdbcTemplate.queryForObject(sql,new RowCallBackHandler(){ public Object processRow(ResultSet rs) { BookMaping map = new BookMaping(); Book book = (Book)map.mapping(rs,new Book()); return book; } }); } public List queryByAuthor(String author) { String sql = "select * from book where author = "+author; return jdbcTemplate.query(sql,new RowCallBackHandler(){ public Object processRow(ResultSet rs) { BookMaping map = new BookMaping(); Book book = (Book)map.mapping(rs,new Book()); return book; } }); } //Borrower的具体实现: //BookDaoImpl.java package edu.jlu.fuliang.library.dao.mysql; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import edu.jlu.fuliang.library.dao.BorrowerDao; import edu.jlu.fuliang.library.domain.Borrower; import edu.jlu.fuliang.library.jdbc.JdbcTemplate; import edu.jlu.fuliang.library.jdbc.PreparedStatementCallBack; import edu.jlu.fuliang.library.jdbc.RowCallBackHandler; public class BorrowerDaoImpl implements BorrowerDao{ private JdbcTemplate jdbcTemplate = new JdbcTemplate(); public Borrower queryByLastName(String lastName) { String sql = "select * from borrower where lastName = " + lastName; return (Borrower)jdbcTemplate.queryForObject(sql,new RowCallBackHandler(){ public Object processRow(ResultSet rs) { BorrowerMaping borrowerMaping = new BorrowerMaping(); return borrowerMaping.mapping(rs,new Borrower()); } }); } public void updateBorrower(final Borrower borrower) { String sql = "update borrower set lastname = ?,firstname=?" + ",address =?,city =?,zip=?,state=? where lastname = ?"; jdbcTemplate.executeUpdate(sql,new PreparedStatementCallBack(){ public void doInStatement(PreparedStatement stmt) throws SQLException { stmt.setString(1,borrower.getLastName()); stmt.setString(2,borrower.getFirstName()); stmt.setString(3,borrower.getAddress()); stmt.setString(4,borrower.getCity()); stmt.setString(5,borrower.getZip()); stmt.setString(6,borrower.getState()); stmt.setString(7,borrower.getLastName()); } }); } public void insertBorrower(final Borrower borrower) { String sql = "insert into borrower values(?,?,?,?,?,?)"; jdbcTemplate.executeUpdate(sql,new PreparedStatementCallBack(){ public void doInStatement(PreparedStatement stmt) throws SQLException { stmt.setString(1,borrower.getLastName()); stmt.setString(2,borrower.getFirstName()); stmt.setString(3,borrower.getAddress()); stmt.setString(4,borrower.getCity()); stmt.setString(5,borrower.getZip()); stmt.setString(6,borrower.getState()); } }); } public void deleteBorrowerByLastName(final String lastName) { String sql = "delete from borrower where lastName = ?"; jdbcTemplate.executeUpdate(sql,new PreparedStatementCallBack(){ public void doInStatement(PreparedStatement stmt) throws SQLException { stmt.setString(1,lastName); } }); } } // BorrowOrReturnDaoImpl.java package edu.jlu.fuliang.library.dao.mysql; import java.sql.PreparedStatement; import java.sql.SQLException; import edu.jlu.fuliang.library.dao.BorrowOrReturnDao; import edu.jlu.fuliang.library.jdbc.JdbcTemplate; import edu.jlu.fuliang.library.jdbc.PreparedStatementCallBack; public class BorrowOrReturnDaoImpl implements BorrowOrReturnDao{ private JdbcTemplate jdbcTemplate = new JdbcTemplate(); public void borrowBook(final String borrowerLastName, final String bookTitle) { String sql = "insert into book_borrower values(?,?)"; jdbcTemplate.executeUpdate(sql,new PreparedStatementCallBack(){ public void doInStatement(PreparedStatement stmt) { try{ stmt.setString(1,borrowerLastName); stmt.setString(2,bookTitle); }catch(SQLException e){ e.printStackTrace(); } } }); } public void returnBook(final String borrowerLastName, final String bookTitle) { String sql = "delete from book_borrower where lastname = ?,title = ?"; jdbcTemplate.executeUpdate(sql,new PreparedStatementCallBack(){ public void doInStatement(PreparedStatement stmt) { try{ stmt.setString(1,borrowerLastName); stmt.setString(2,bookTitle); }catch(SQLException e){ e.printStackTrace(); } } }); } } //book的ORMaping的实现: // BookMaping.java package edu.jlu.fuliang.library.dao.mysql; import java.sql.ResultSet; import java.sql.SQLException; import edu.jlu.fuliang.library.domain.Book; import edu.jlu.fuliang.library.jdbc.ORMaping; public class BookMaping implements ORMaping{ public Object mapping(ResultSet rs, Object o) { Book book = (Book)o; try { book.setTitleName(rs.getString("titleName")); book.setAuthor(rs.getString("author")); book.setISBN(rs.getString("isbn")); book.setType(rs.getInt("type")); book.setItemsAvailable(rs.getInt("itemAvailable")); } catch (SQLException e) { e.printStackTrace(); } return book; } } ////borrower的ORMaping的实现: // BorrowerMaping.java package edu.jlu.fuliang.library.dao.mysql; import java.sql.ResultSet; import java.sql.SQLException; import edu.jlu.fuliang.library.domain.Borrower; import edu.jlu.fuliang.library.jdbc.ORMaping; public class BorrowerMaping implements ORMaping{ public Object mapping(ResultSet rs, Object o) { Borrower borrower = (Borrower)o; try { borrower.setLastName(rs.getString(1)); borrower.setFirstName(rs.getString(2)); borrower.setAddress(rs.getString(3)); borrower.setCity(rs.getString(4)); borrower.setZip(rs.getString(5)); borrower.setState(rs.getString(6)); } catch (SQLException e) { e.printStackTrace(); } return borrower; } }
50 楼
intolong
2007-02-25
ajoo不是写过jdbc template么?
http://www.iteye.com/topic/7068
和你同事那个差不多吧,一个继承,一个组合
http://www.iteye.com/topic/7068
和你同事那个差不多吧,一个继承,一个组合
49 楼
jianfeng008cn
2007-02-25
fuliang 写道
使用jdbc,可以使用Spring对jdbc的封装,感觉还是比较好用的,
如果你不打算使用Spring,也可以使用Template method模式和
回调方法来封装对jdbc的低级操作(具体可参见Spring的实现)。
当然使用ibatis可以大大减少许多低级操作,而且学习非常容易,
感觉还是有必要在公司推广。当然hibernate是不错的选择,不过
学习难度比ibatis大点。
不过我一直对持久层技术存在一些疑惑:
无论是jdbc、ibatis、hibernate,当使用Dao模式进行封装分离出
持久化层时,当业务需求增加或变化时,dao往往也许要发生变化,例
如查询文章,以前根据title,现在又需要根据id,这就需要增加新的
方法,觉得很不爽。如果能够直接设置Example的状态,根据这个对象
的非null属性来查询(当然需要支持复杂的情况,如title满足简单的
正则表达式,整数的范围等)。只需要一个方法,传递一个对象就可以查
询满足的对象。rails的ActiveRecord,能够动态的产生查询方法(
find_by_id(),find_by_title()),没有了dao层,但需求增加时,不需要修改原来的代码,感觉还是不错的。
如果你不打算使用Spring,也可以使用Template method模式和
回调方法来封装对jdbc的低级操作(具体可参见Spring的实现)。
当然使用ibatis可以大大减少许多低级操作,而且学习非常容易,
感觉还是有必要在公司推广。当然hibernate是不错的选择,不过
学习难度比ibatis大点。
不过我一直对持久层技术存在一些疑惑:
无论是jdbc、ibatis、hibernate,当使用Dao模式进行封装分离出
持久化层时,当业务需求增加或变化时,dao往往也许要发生变化,例
如查询文章,以前根据title,现在又需要根据id,这就需要增加新的
方法,觉得很不爽。如果能够直接设置Example的状态,根据这个对象
的非null属性来查询(当然需要支持复杂的情况,如title满足简单的
正则表达式,整数的范围等)。只需要一个方法,传递一个对象就可以查
询满足的对象。rails的ActiveRecord,能够动态的产生查询方法(
find_by_id(),find_by_title()),没有了dao层,但需求增加时,不需要修改原来的代码,感觉还是不错的。
既然想到了 何不搞个出来 这段话下面贴个附件带上你的demo 该有多漂亮 呵呵
48 楼
fuliang
2007-02-24
使用jdbc,可以使用Spring对jdbc的封装,感觉还是比较好用的,
如果你不打算使用Spring,也可以使用Template method模式和
回调方法来封装对jdbc的低级操作(具体可参见Spring的实现)。
当然使用ibatis可以大大减少许多低级操作,而且学习非常容易,
感觉还是有必要在公司推广。当然hibernate是不错的选择,不过
学习难度比ibatis大点。
不过我一直对持久层技术存在一些疑惑:
无论是jdbc、ibatis、hibernate,当使用Dao模式进行封装分离出
持久化层时,当业务需求增加或变化时,dao往往也许要发生变化,例
如查询文章,以前根据title,现在又需要根据id,这就需要增加新的
方法,觉得很不爽。如果能够直接设置Example的状态,根据这个对象
的非null属性来查询(当然需要支持复杂的情况,如title满足简单的
正则表达式,整数的范围等)。只需要一个方法,传递一个对象就可以查
询满足的对象。rails的ActiveRecord,能够动态的产生查询方法(
find_by_id(),find_by_title()),没有了dao层,但需求增加时,不需要修改原来的代码,感觉还是不错的。
如果你不打算使用Spring,也可以使用Template method模式和
回调方法来封装对jdbc的低级操作(具体可参见Spring的实现)。
当然使用ibatis可以大大减少许多低级操作,而且学习非常容易,
感觉还是有必要在公司推广。当然hibernate是不错的选择,不过
学习难度比ibatis大点。
不过我一直对持久层技术存在一些疑惑:
无论是jdbc、ibatis、hibernate,当使用Dao模式进行封装分离出
持久化层时,当业务需求增加或变化时,dao往往也许要发生变化,例
如查询文章,以前根据title,现在又需要根据id,这就需要增加新的
方法,觉得很不爽。如果能够直接设置Example的状态,根据这个对象
的非null属性来查询(当然需要支持复杂的情况,如title满足简单的
正则表达式,整数的范围等)。只需要一个方法,传递一个对象就可以查
询满足的对象。rails的ActiveRecord,能够动态的产生查询方法(
find_by_id(),find_by_title()),没有了dao层,但需求增加时,不需要修改原来的代码,感觉还是不错的。
47 楼
eonhy
2007-02-14
ibatis在遗留系统改造中使用,它对原有JDBC代码的替换可以说是思路清晰,相当容易上手!
Hibernate用在新设计的系统中,也很容易掌握,难点在于,如果像我所遇到的,表与表之间存在外键,存在多对一和多对多的关系的时候,设计上的不合理就会在运行效率中明显的体现出来,这差点让一个项目在中途进行大规模重构!
Hibernate用在新设计的系统中,也很容易掌握,难点在于,如果像我所遇到的,表与表之间存在外键,存在多对一和多对多的关系的时候,设计上的不合理就会在运行效率中明显的体现出来,这差点让一个项目在中途进行大规模重构!
46 楼
aardvark
2007-02-13
ajoo 写道
我其实也反对开发自己的“框架”。自己的库还成。Framework嘛,现在一听这个词就头疼。
可惜,我们现在自己开发的Framework不管好不好,都顶着一个“公司标准,一致性”的大帽子,你不用都不行。
这个遗留系统里面自己的框架多了,有mvc, property, ioc, persistence。都是作的比较古怪,灵活性,可用性和简单性都比较差,跟业界标准也不那么兼容。
比如,persistence框架里自己弄一个MyConnection,而不是java.sql.Connection。
property框架自己内部通过某种逻辑决定ClassLoader,而这个ClassLoader从外界无法得到,所以也无法和别的开源框架兼容。自己弄的MyProperties不实现java.util.Map。
等等等等。
不过,软件这东西,真是公说公有理的事情。就一个“一致性”就几乎可以枪毙一切改进措施了。
spring template我们暂时还是不用。不太想引入spring的依赖。毕竟我们还不到替换自己的ioc的时候。
commons dbutil倒是轻量的多。不过和我们的自制persistence不太兼容,也不能帮我们做cache。
hibernate嘛,要的改动就大得多了,学习曲线也陡,我自己都不能说服自己采用。毕竟现在的persistence框架上和概念上和ibatis是最接近的。
可惜,我们现在自己开发的Framework不管好不好,都顶着一个“公司标准,一致性”的大帽子,你不用都不行。
这个遗留系统里面自己的框架多了,有mvc, property, ioc, persistence。都是作的比较古怪,灵活性,可用性和简单性都比较差,跟业界标准也不那么兼容。
比如,persistence框架里自己弄一个MyConnection,而不是java.sql.Connection。
property框架自己内部通过某种逻辑决定ClassLoader,而这个ClassLoader从外界无法得到,所以也无法和别的开源框架兼容。自己弄的MyProperties不实现java.util.Map。
等等等等。
不过,软件这东西,真是公说公有理的事情。就一个“一致性”就几乎可以枪毙一切改进措施了。
spring template我们暂时还是不用。不太想引入spring的依赖。毕竟我们还不到替换自己的ioc的时候。
commons dbutil倒是轻量的多。不过和我们的自制persistence不太兼容,也不能帮我们做cache。
hibernate嘛,要的改动就大得多了,学习曲线也陡,我自己都不能说服自己采用。毕竟现在的persistence框架上和概念上和ibatis是最接近的。
我觉得你还是在从技术层面看问题,还是过于急迫地进入细节。
第一步,不预设任何方案,说服同事选择开源框架,而避免陷入自己开放又一个框架的泥潭;
第二步,你们一起选择一个合适的开源框架。
到底选择哪一个,等解决了第一步以后再说。如果ibatis真的是最适合你们的方案,我相信一旦你们进入第二步,在同事的参与下你们最终会选择ibatis。与其去推销自己的选择,不如引导他作出同样的选择。
45 楼
ajoo
2007-02-13
我其实也反对开发自己的“框架”。自己的库还成。Framework嘛,现在一听这个词就头疼。
可惜,我们现在自己开发的Framework不管好不好,都顶着一个“公司标准,一致性”的大帽子,你不用都不行。
这个遗留系统里面自己的框架多了,有mvc, property, ioc, persistence。都是作的比较古怪,灵活性,可用性和简单性都比较差,跟业界标准也不那么兼容。
比如,persistence框架里自己弄一个MyConnection,而不是java.sql.Connection。
property框架自己内部通过某种逻辑决定ClassLoader,而这个ClassLoader从外界无法得到,所以也无法和别的开源框架兼容。自己弄的MyProperties不实现java.util.Map。
等等等等。
不过,软件这东西,真是公说公有理的事情。就一个“一致性”就几乎可以枪毙一切改进措施了。
spring template我们暂时还是不用。不太想引入spring的依赖。毕竟我们还不到替换自己的ioc的时候。
commons dbutil倒是轻量的多。不过和我们的自制persistence不太兼容,也不能帮我们做cache。
hibernate嘛,要的改动就大得多了,学习曲线也陡,我自己都不能说服自己采用。毕竟现在的persistence框架上和概念上和ibatis是最接近的。
可惜,我们现在自己开发的Framework不管好不好,都顶着一个“公司标准,一致性”的大帽子,你不用都不行。
这个遗留系统里面自己的框架多了,有mvc, property, ioc, persistence。都是作的比较古怪,灵活性,可用性和简单性都比较差,跟业界标准也不那么兼容。
比如,persistence框架里自己弄一个MyConnection,而不是java.sql.Connection。
property框架自己内部通过某种逻辑决定ClassLoader,而这个ClassLoader从外界无法得到,所以也无法和别的开源框架兼容。自己弄的MyProperties不实现java.util.Map。
等等等等。
不过,软件这东西,真是公说公有理的事情。就一个“一致性”就几乎可以枪毙一切改进措施了。
spring template我们暂时还是不用。不太想引入spring的依赖。毕竟我们还不到替换自己的ioc的时候。
commons dbutil倒是轻量的多。不过和我们的自制persistence不太兼容,也不能帮我们做cache。
hibernate嘛,要的改动就大得多了,学习曲线也陡,我自己都不能说服自己采用。毕竟现在的persistence框架上和概念上和ibatis是最接近的。
44 楼
aardvark
2007-02-13
这个问题从一开始就不是一个技术问题。试图从技术的角度来说服同事用ibatis,效果自然不会好。<br/>
<br/>
如果要从技术的角度来说的话,站在同事的立场,ibatis在技术上没有带来显著的好处。ibatis能实现的,或者自己用jdbc也能实现,或者他觉得没有必 要实现。每个人都倾向于选择自己熟悉的方案,因为心里有底。不用ibatis的好处是显而易见的:一、什么也不用学;二、拥有几乎无限度的灵活性。如果将来需要什么功能,凭着对 jdbc的熟悉,可以随时添加必要的功能。<br/>
<br/>
要说服同事,就必须上到更高的台阶来看这个问题:是自己开发框架,还是用现成的。<br/>
<br/>
用jdbc写简单的框架虽然有这样那样的好处,但坏处是致命的:维护成本。现在你们可能还不觉得什么,只是做了个很简单的框架而已。可是今天觉得缺少这个功能,就添加之;明天又觉得那个地方以前没有考虑到,再修改之。时间长了,这个简单的框架就会不再简单,到最后你们就会发现有了个自己的不怎么样的ORM框架。即时你们有意识地控制这个框架的规模,也还是很难。特别是对于技术素质好的人来说,没有办法容忍自己框架的这样那样的不好。结果就是,在这个框架中越陷越深。相对于用现成的开源框架来说,开源框架有一个team在维护,对你们来说就是0成本维护,而且还比自己维护自己框架的效果好。<br/>
<br/>
自己开发框架并不是没有学习成本。开发框架的人是可以不用学,但以后再招人,如果用了现成的框架,可以直接招懂这个框架的人;如果自己开发框架,新招近来的人必须有一个学习的过程,而且更糟的是自己开发的框架还没有什么完善的文档。长远地看用自己的框架的学习成本反而比用现成的要高。<br/>
<br/>
其实只要是用一个现成的框架,不管是ibatis还是hibernate还是spring jdbc template还是什么别的,都比自己开发一个框架强。这样你们可以把精力集中在解决领域问题上,而不是分散在维护自己的框架上。<br/>
<br/>
我在工作中不得不用大量的精力维护我们自己的不怎么样的MVC框架和ORM框架。明天我离开这个公司,后来的人同样要花精力学习和维护这两个框架。<br/>
<br/>
并不是绝对地反对做自己的框架。如果自己有独到的想法,可以实现现有的框架做不到的,完全可以开发一个新的框架。但是,如果真有这个需要,我也宁愿把这个框架开源。一来可以从别人的反馈中更好地发展这个框架,二来也可以有其他的人加入进来,共同发展它。同样是开发框架,比作为一个内部项目来开发就要强得多了。<br/>
<br/>
基于这样的理由,我是坚决反对在公司内部发展自己的框架。建议你先和同事解决“开发自己的框架还是用现成的框架”的问题,然后再具体探讨用哪个框架。<br/>
<br/>
你也不要局限在ibatis上。<br/>
提示一:也许spring jdbc template是一个比较好的折中<br/>
提示二:hibernate也可以用作jdbc框架 <br/>
<a href='http://www.theserverside.com/tt/blogs/showblog.tss?id=Hibernate3_JDBC'>www.theserverside.com/tt/blogs/showblog.tss</a>
<br/>
如果要从技术的角度来说的话,站在同事的立场,ibatis在技术上没有带来显著的好处。ibatis能实现的,或者自己用jdbc也能实现,或者他觉得没有必 要实现。每个人都倾向于选择自己熟悉的方案,因为心里有底。不用ibatis的好处是显而易见的:一、什么也不用学;二、拥有几乎无限度的灵活性。如果将来需要什么功能,凭着对 jdbc的熟悉,可以随时添加必要的功能。<br/>
<br/>
要说服同事,就必须上到更高的台阶来看这个问题:是自己开发框架,还是用现成的。<br/>
<br/>
用jdbc写简单的框架虽然有这样那样的好处,但坏处是致命的:维护成本。现在你们可能还不觉得什么,只是做了个很简单的框架而已。可是今天觉得缺少这个功能,就添加之;明天又觉得那个地方以前没有考虑到,再修改之。时间长了,这个简单的框架就会不再简单,到最后你们就会发现有了个自己的不怎么样的ORM框架。即时你们有意识地控制这个框架的规模,也还是很难。特别是对于技术素质好的人来说,没有办法容忍自己框架的这样那样的不好。结果就是,在这个框架中越陷越深。相对于用现成的开源框架来说,开源框架有一个team在维护,对你们来说就是0成本维护,而且还比自己维护自己框架的效果好。<br/>
<br/>
自己开发框架并不是没有学习成本。开发框架的人是可以不用学,但以后再招人,如果用了现成的框架,可以直接招懂这个框架的人;如果自己开发框架,新招近来的人必须有一个学习的过程,而且更糟的是自己开发的框架还没有什么完善的文档。长远地看用自己的框架的学习成本反而比用现成的要高。<br/>
<br/>
其实只要是用一个现成的框架,不管是ibatis还是hibernate还是spring jdbc template还是什么别的,都比自己开发一个框架强。这样你们可以把精力集中在解决领域问题上,而不是分散在维护自己的框架上。<br/>
<br/>
我在工作中不得不用大量的精力维护我们自己的不怎么样的MVC框架和ORM框架。明天我离开这个公司,后来的人同样要花精力学习和维护这两个框架。<br/>
<br/>
并不是绝对地反对做自己的框架。如果自己有独到的想法,可以实现现有的框架做不到的,完全可以开发一个新的框架。但是,如果真有这个需要,我也宁愿把这个框架开源。一来可以从别人的反馈中更好地发展这个框架,二来也可以有其他的人加入进来,共同发展它。同样是开发框架,比作为一个内部项目来开发就要强得多了。<br/>
<br/>
基于这样的理由,我是坚决反对在公司内部发展自己的框架。建议你先和同事解决“开发自己的框架还是用现成的框架”的问题,然后再具体探讨用哪个框架。<br/>
<br/>
你也不要局限在ibatis上。<br/>
提示一:也许spring jdbc template是一个比较好的折中<br/>
提示二:hibernate也可以用作jdbc框架 <br/>
<a href='http://www.theserverside.com/tt/blogs/showblog.tss?id=Hibernate3_JDBC'>www.theserverside.com/tt/blogs/showblog.tss</a>
43 楼
ajoo
2007-02-13
cat 写道
题外话:有时候一个程序code没几行,底下XML暗涛汹涌,出点问题还真不好找。可能这也是代码生成的好处之一吧。
不过iBatis看起来还是挺简单,虽然没用过,不过似乎还不至于那么难调。我们用一套存储过程的Wrapper, 是代码生成的,挺方便。
不过iBatis看起来还是挺简单,虽然没用过,不过似乎还不至于那么难调。我们用一套存储过程的Wrapper, 是代码生成的,挺方便。
ibatis允许配置DataSourceFactory。
我用dynamic proxy把所有的jdbc call都拦截了,这样调试起来其实更方便。
42 楼
cat
2007-02-11
题外话:有时候一个程序code没几行,底下XML暗涛汹涌,出点问题还真不好找。可能这也是代码生成的好处之一吧。
不过iBatis看起来还是挺简单,虽然没用过,不过似乎还不至于那么难调。我们用一套存储过程的Wrapper, 是代码生成的,挺方便。
不过iBatis看起来还是挺简单,虽然没用过,不过似乎还不至于那么难调。我们用一套存储过程的Wrapper, 是代码生成的,挺方便。
41 楼
lordhong
2007-02-10
你一个architect连决定用什么技术的权力都没有,还算什么architect啊?
40 楼
TinyJimmy
2007-02-10
你有两种选择, 说服大家使用新的技术, 要么加入一个能否让你使用新技术的团队.
By the way, 不要总想着改变人, 特别是大多数人, 能改变的是你自己. 包括你的决定和做事情的方法
By the way, 不要总想着改变人, 特别是大多数人, 能改变的是你自己. 包括你的决定和做事情的方法
39 楼
wuyingsong
2007-02-09
这都要感谢SPRING提供的 HibernateDaoSupport ,它的功能太强大了
38 楼
wuyingsong
2007-02-09
在SERVICE层直接调用DAO就行了
发表评论
-
getThis().getEvilAdvocate().setDead(getTrue())
2008-08-14 04:15 3694code review过程中,看到这样的代码: Pair& ... -
怎样最有效地测试异常?
2008-04-02 21:56 4851工作中,和同事对测试 ... -
DRY与简单性的平衡
2007-02-16 18:45 5593这个事例说起来相当简单。不过小中见大,它大致体现了我和pair ... -
Web AOP?
2007-02-16 11:12 6144今天这个其实不是争论。 这是我接手的一个web系统的一个设计 ... -
依赖是否可以作为一个独立的衡量软件质量的标准?
2007-02-12 05:03 8078这个争论的背景有点复杂。我就尽量简化了说。 遗留系统有一个自 ... -
这样代码重用?
2007-02-12 03:09 19528这是一个工作中遇到的 ... -
一致性和Use Right Tool For Right Job哪个重要?
2007-02-05 12:52 5576这个争执发生在测试的时候。 背景是这样的: 一个接口有很多乱七 ... -
关于 Replace Temp With Query
2007-02-05 11:55 8825这个I disagree系列里面我 ... -
复杂还是不复杂?
2007-02-04 04:01 10426问题是这样的。 一个My ...
相关推荐
本篇文章将深入探讨iBATIS3和JDBC在性能上的对比,以帮助开发者更好地理解这两种技术的优劣。 iBATIS3是一个轻量级的持久层框架,它提供了一种将SQL语句与Java代码分离的方式,通过XML或注解来定义SQL映射,增强了...
标题中的"springmvc_hibernate_ibatis_jdbc"指的是一个整合了SpringMVC、Hibernate、iBatis和JDBC这四种关键技术的Java应用框架。这个框架旨在提供一个全面且强大的解决方案,便于开发人员进行Web应用程序的构建。 ...
### MySQL、JDBC详解及与iBatis对比 #### 一、MySQL基本操作 MySQL作为一款广泛使用的开源关系型数据库管理系统,在IT行业中占有极其重要的地位。对于开发人员来说,掌握MySQL的基本操作至关重要。 ##### 1. 增删...
在源码中,`org.apache.ibatis.transaction.jdbc.JdbcTransaction`和`org.apache.ibatis.transaction.managed.ManagedTransaction`分别对应JDBC和Spring的事务管理。 十、缓存机制 iBatis提供了本地缓存和二级缓存...
iBATIS是一个由Clinton Begin创建,目前由Apache基金会支持的持久化框架,它专注于数据库查询的简化,尤其在JDBC编程方面提供了极大的便利。相对于全自动化ORM解决方案如Hibernate,iBATIS被称为“半自动化”ORM实现...
这里设置事务管理器类型为JDBC,表示ibatis将直接使用底层的JDBC连接进行事务控制,而不是使用Spring提供的事务管理器。 ```xml <transactionManager type="JDBC"> <property value="oracle.jdbc.driver....
Ibatis的出现,解决了传统JDBC中手动编写SQL和结果集映射的繁琐工作,提供了更加灵活的数据访问接口。 在"ibatis demo"中,我们通常会看到以下核心概念和知识点: 1. **配置文件**:Ibatis的配置文件(mybatis-...
相较于传统的 JDBC,Ibatis 提供了更灵活的数据访问层,使得数据库操作更加简洁高效。 二、Ibatis 安装与配置 1. 添加依赖:在 Maven 项目中,需要在 `pom.xml` 文件中添加 Ibatis 的依赖。 2. 配置文件:创建 `...
Ibatis,全称为MyBatis,是一个优秀的Java持久层框架,它主要负责SQL映射,使得开发者能够将注意力集中在编写SQL语句上,而无需关注...因此,无论你是初学者还是有经验的开发者,掌握Ibatis都是提升自己技能的好选择。
"IBATISJDBC包"指的是包含了用于支持IBATIS框架运行所需的JDBC(Java Database Connectivity)驱动及相关依赖的集合。在MYECLIPSE这样的集成开发环境中,这些JAR包是必不可少的,因为它们使得开发者能够无缝地将...
与传统的JDBC相比,Ibatis提供了一种更方便、更易于维护的方式来处理数据库交互。 在使用Ibatis时,首先需要配置数据源,这是通过DataSource接口实现的,常见的实现有Apache的DBCP和C3P0等。接着,我们需要创建...
这样的配置意味着iBatis将使用JDBC的方式进行事务管理,即所有的事务控制逻辑都由iBatis负责,而不是由Spring的事务管理器来处理。 ### 手动控制事务 在实际的应用开发中,如果希望保留iBatis的事务管理机制并能够...
最后,还讨论了iBATIS的优缺点,及为什么是这样的一种方式,即所谓的“在完全OR与JDBC之间的一个幽雅的折衷。” <br>就象Developer's Notebook 系列中所有的书一样,你将由直接的且实用的方式获得信息,这些信息...
### Ibatis3手册知识点概述 Ibatis3作为一款流行的持久层框架,在软件开发领域具有重要的地位。本篇文章基于“Ibatis3手册 Ibatis3参考手册”的标题及描述,深入解析Ibatis3的核心概念、架构特点以及如何进行实际...
iBatis 是一款轻量级的Java持久层框架,它主要负责将数据库操作与业务逻辑解耦,使得开发者可以更加专注于SQL和业务代码的编写。...无论是简单还是复杂的数据库操作,iBatis都能够提供有效的解决方案。
而 iBATIS 是一个持久层框架,它封装了 JDBC,使得 SQL 查询操作更加简洁。 **SpringMVC 知识点** 1. **DispatcherServlet**: SpringMVC 的核心组件,作为前端控制器接收请求并分发到对应的处理器。 2. **Model-...
3. **JDBC驱动设置**: - 在数据库连接时,通过`Connection`对象的`setCharacterEncoding()`方法设置字符集,确保与数据库保持一致。 4. **SQL语句处理**: - 如果在动态SQL中涉及到字符串拼接,务必确保字符串...
4. **连接池**:C3P0 是一个开源的 JDBC 连接池,它实现了数据源和 JNDI 绑定,提供了性能优化功能。在整合中,我们需要配置 C3P0 数据源,以便为应用程序提供高效的数据库连接管理。 5. **配置整合**:在 ...
Ibatis 是一个优秀的开源持久层框架,它允许开发者将 SQL 查询与 Java 代码分离,从而避免了传统的 JDBC 编程中的大量模板代码。作为一个轻量级的框架,Ibatis 提供了灵活的映射机制,使得 XML 或注解方式的 SQL ...
3. SQL Server JDBC驱动:Ibatis通过JDBC与数据库交互,因此需要对应的驱动jar包。对于SQL Server 2005,你需要`sqljdbc4.jar`。 接下来,我们逐步进行环境配置: **1. 创建项目结构** 创建一个新的Java项目,并...