ORM 可以做什么
基础规范的不足
jdbc 是java 应用程序数据持久化的基础,也是众多数据库厂商与java 的接口。直接使用jdbc 编写代码非常繁琐,比如数据库资源的获得和释放,异常捕获和事务处理等等,重复代码多是他的一个特点。另外,不同的数据库,在数据类型,主键类型还是sql 语句都和SQL 标准小有出入,所以如何使应用程序可以在不同数据库平台方便的迁移,也是个问题。
开发框架的解决方案
spring 和hibernate 的出现使情况大为好转,spring 面向切面管理事务, hibernate 自动ORM 可以大大简化开发,spring 和hibernate 都有.net 的版本,这证明了他们的成功。但是“用好hibernate ,需要扎实的掌握关系模型和SQL ”,同时对面向对象设计和hibernate 自身的运行机制也要有非常清晰的认识,只有这种水平才能发挥hibernate 的威力,降低hibernate 带来的风险。所以,在合适的层面上配置好spring 的事务管理,设计好对象模型,把对hibernate 的直接使用控制在一定范围内是设计者要解决的基本问题。如果设计不佳,或者直接交给初出校门的开发者去用,那这种组合就会变成洪水猛兽,同时也不利于团队成员的成长。
我们的选择
如果只有jdbc ,我们的系统也可以工作,只不过要写很多重复和机械的代码,通过框架的ORM 的映射,可以将数据库表的数据自动填入javabean ,这节省了劳动力,也使系统结构自然清晰。如果不用ORM 工具,我们能不能通过某种形式来模拟他的行为呢?我们可以创建这样一个接口:
Java代码
public interface IOper { boolean load(Connection connect) throws SQLException; boolean add(Connection connect) throws SQLException; boolean update(Connection connect) throws SQLException; boolean delete(Connection connect) throws SQLException; }
在接口中定义 CRUD 方法。返回类型为 boolean 而非影响的行数,意图是对象内部的操作可能是复杂的多步骤的,所以对他的上层应用来说,知道结果成功与否就可以了。接下来在他的实现类里可以这么写:
Java代码
public class Worker implements IOper { // Fields private Integer workerId; private String workerName; private String logonName; private String logonPwd; /* * 对于允许为空的字段赋予初始值,避免页面显示null */ private String mobile = ""; private String email = ""; private String remark = ""; private String isFreeze = "0"; // Constructors /** default constructor */ // Property accessors public boolean add(Connection connect) throws SQLException { SQLBuffer sql = new SQLBuffer(); sql.segment("insert into worker (worker_name,logon_name,logon_pwd,"); sql.segment("mobile,email,remark,is_freeze) values ("); sql.value(this.workerName); sql.comma(); sql.value(this.logonName); sql.comma(); sql.value(this.logonPwd); sql.comma(); sql.value(this.mobile); sql.comma(); sql.value(this.email); sql.comma(); sql.value(this.remark); sql.comma(); sql.value(this.isFreeze); sql.segment(")"); return Proxy.update(connect, sql) == 1; } public boolean delete(Connection connect) throws SQLException { // 冻结用户 SQLBuffer sql = new SQLBuffer(); sql.segment("update worker set is_isfreeze = "); this.isFreeze = "1"; sql.value(this.isFreeze); sql.segment(" where worker_id = "); sql.value(this.workerId); return Proxy.update(connect, sql) == 1; } public boolean load(Connection connect) throws SQLException { SQLBuffer sql = new SQLBuffer( "select worker_name,logon_name,logon_pwd,mobile,email,remark,is_freeze from worker"); sql.segment(" where worker_id = "); sql.value(this.workerId); MapRow mr = Proxy.getMapRow(connect, sql); if (mr == null) { return false; } this.workerName = mr.getString("worker_name"); this.logonName = mr.getString("logon_name"); this.logonPwd = mr.getString("logon_pwd"); this.mobile = mr.getString("mobile"); this.email = mr.getString("email"); this.remark = mr.getString("remark"); this.isFreeze = mr.getString("is_freeze"); return true; } public boolean update(Connection connect) throws SQLException { SQLBuffer sql = new SQLBuffer(); sql.segment("update worker set worker_name = "); sql.value(this.workerName); sql.segment(", logon_name = "); sql.value(this.logonName); sql.segment(", logon_pwd = "); sql.value(this.logonPwd); sql.segment(", mobile = "); sql.value(this.mobile); sql.segment(", email = "); sql.value(this.email); sql.segment(", remark = "); sql.value(this.remark); sql.segment(", is_freeze = "); sql.value(this.isFreeze); sql.segment(" where worker_id = "); sql.value(this.workerId); return Proxy.update(connect, sql) == 1; } }