开发者学堂课程【DAO 开发实战业务分析:OR-Mapping 设计改进(数据增加改进)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/399/detail/5178
OR-Mapping 设计改进(数据增加改进)
内容介绍:
一、增加数据的操作步骤
二、具体内容
三、总结
一、增加数据的操作步骤
如果要想实现数据增加控制,现在所有的操作一定要通过类结构取得,所以对于增加数据的操作应该分为如下几个步骤:
1、动态生成一个 SQL 语句;
2、根据这个 SQL 语句创建 PreparedStatement 对象;
3、根据生成的 SQL 语句的结构,然后动态地进行设置 PreparedStatement 接口的数据;
4、执行数据的更新处理操作。
其中有一个功能方法,即 public boolean ,严格来讲应该返回一个id主键,id主键可能是整型或者是字符串,所以更严格来讲应该返回 Serizliable ,但现在的开发主要是提供设计思想,所以返回 boolean 即可。
创建的处理过程通过跟上 createSupport() {,即 public boolean createSupport() {来实现数据的增加处理操作,增加成功返回true,否则返回false,从而做简化处理。此时需要参数 Object vo ,即 public boolean createSupport(Object vo) {,因为所有的位都可能使用到。
首先表示出在此的操作处理过程之中要进行增加数据处理的 VO 类对象,即表示为@param vo 要进行增加数据处理的 VO 类对象。
二、具体内容
1.在AbstractDAO类里面追加一个增加的控制支持方法,如下:
/**
* 实现数据的增加处理操作
* @param vo 要进行增加数据处理的VO类对象
* @return 增加成功返回true,否则返回false
*/
public boolean createSupport(Object vo) {
return false ;
}
2、既然要实现追加数据操作,就建议有一个单独类去实现;
· 创建一个 cn.mldn.util.dao.support.InsertSupport 类,将 Insert 写为 Create 也可以,如下:
package cn.mldn.util.dao.support;
/**
* 此类主要完善增加操作的PreparedStatement内容设置、更新执行以及SQL语句创建
* @author mldn
*
*/
public class CreateSupport {
}
如果想要创建的时候,需要有补充位。如果要想追加控制,整个过程要交给
CreateSupport support = new CreateSupport();,在这里进行对对象的操作控制。
在位中应该通过 public String createSQL() {} 方法进行操作。而最关键的问题是很多都需要 createSQL(),可以将其变为接口进行操作。
此时要求传入 Object vo,即 public String createSQL(Object vo) {},从而要创建增加数据的 SQL 语句。如果要创建,就要进行大量的修改,一旦要进行修改,就要通过 StringBuffer buf = new StringBuffer();,再进行跟上 return buf.toString() ;来进行操作。
此时要进行追加,追加的语句为 Insert INTO member(mid,name,age,phone,birthday,note)VALUES(?,?,?,?,?,?),类名称可以通过String tableName = vo.getClass().getSimpleName();来取得,类名称即为表名称。
如果表名称与类名称不一致,再加配置文件,将二者对在一起。
完成以上操作后,再通过代码
String idColumn = Resource.getId(vo.getClass.getName());取得主键,取得主键列后问号也同时产生,所以要有两个StringBuffer,一个是用来控制列,另一个是用来控制问号的,而且要记录好第一个问号是mid,
第二个问号是 name,否则无法设置值。所以在代码中增加 Map ,即Private Map<Integer,String> columnsMap = new HashMap<Integer,String>() ;从而用来定义序号以及列名称的关系,有了名字就可以操作其中的属性内容。
然后在代码中添加 bufHead 和 bufTail ,即表示为 StringBuffer bufHead = new StringBuffer();和StringBuffer bufTail = new StringBuffer();,这时还需要一个总的 buf,即StringBuffer buf = new StringBuffer();。写入代码buf.append(“INSERT INTO”).append(tableName).append(“)”);。
取得主键列名称,即追上代码
bufHead.append(“idColunm”) .append(“,”),再追加bufTail.append(“?”).append(“,”);,表示为追加主键列的“?”。追加columnsMap.put(1,idColumn) ;以便用来保存对应关系。随后需要取出所有的其他字段的对应关系,但是这些关系里面不应该再包含有主键列。
再跟上Field voFields [] = vo.getClass().getDEclaredFields();,取得全部的名称,再依次将内容保存到集合里面,同时生成 SQL 语句。
再跟上for(int x = 0 ; x < voFields.length ; x++){,然后进行判断,即
if(!idColumn.equals(voFields[x].getName())) {,如果不一样,表示属性不是主键列,那么现在就可以实现操作。
要先进行保存,即
bufHead.append(voFields[x].getName()).append(“,”);,再进行追加bufTail.append(“?”).append(“,”) ;,处理完成之后,要实现最后的 SQL 拼凑,即要先追加
bufHead.delete(bufHead.length()-1, bufHead.length());,
再跟上
bufTail.delete(bufHead.length()-1, bufHead.length());,首先删除最后的“,“,
再跟上
buf.append(bufHead).qppend(“)VALUES”).append(bufTail).append(“)”),就实现了动态SQL的创建,复合于当前 VO 类的 SQL 语句。
跟上
System.out.println(support.createSQL(vo));,将增加处理部分进行删除后,
跟上
return.super. createSupport(vo);,然后打开 junit 测试,运用 add 代码进行测试,便实现了创建现在所需要用到的SQL语句。
· 在类之中首先实现创建 SQL 的处理,根据反射动态创建。
· 实现 PreparedStatement 的内容设置;
跟上this.pstmt = this.conn.preparedStatement(sql),而 SQL 则为(support.CREATEsql(vo),
即跟上
this.pstmt = this.conn.preparedStatement(support.createSQL(vo))
;,再进行抛出异常。要控制创建内容,进行设置值,即public void setPreparedStatement(PreparedStatement,Object vo) {,因为保存的是序列号和属性名称并没有内容,所以要保存vo。
如果不想传两次,则跟上public Object vo;,
再跟上public CreateSupport(Object vo){,最后跟上 this.vo = vo;,表示在创建对象的时候把 vo 传过去。根据 vo 对象或某一属性取得的值应该属于工具类。
3、现在有了 VO 类的对象,而后又有了操作的属性名称,那么就需要根据属性名称以及对应的 VO 类对象取得其对应的 getter 方法的返回内容。
理论上也应该有一个专门的类负责:cn.mldn.util.BeanValueUtils,如下;
package cn.mldn.util;
public class BeanValueUtils {
private BeanValueUtils() {
public static T getValue(Object obj,String,attributeName,Class<T> cls) {
try {
Method getMethod =
obj.getClass().getMethod(“get” +
StringUtils.initcap(attributeName)) ;
return getMethod.invoke(obj) ;
}catch(Exception e) {
e.printStackTrace();
}
return null ;
}
}
也是可以被重复调用的位。下面的处理采用 for 循环,有多少个属性就循环多少次,所以跟上 for(int x = 1;x <= columnsMap.size() ; x ++){,然后设置内容,但要按照属性操作过于麻烦。如果想开发框架,如下:
package cn.mldn.util.dao;
public class PreparedStatementUtils {
private PreparedStatementUtils() {}
/**
*设置指定序号的PreparedStatement的内容
* @param seq 序号
* @param pstmt PreparedStatement对象
* @param obj 要取得属性内容的对象
* @param attribute 属性的名称
*/
public static void set PreparedStatement(int seq,PreparedStatement pstmt,Object obj,String attribute) throws Exception {
String type = obj.getClass().gerDeclaredField(attribute).getType().getSimpleName() ; //取得属性类型
if(”int“.equals(type) || “Integer”.equals(Type)) {}
pstmt.setInt(seq, BeanValueUtils.getValue(obj,attributeName,Integer.class));
} else if (”double“.equalsIgnoreCase(type)) {
pstmt.setInt(seq, BeanValueUtils.getValue(obj,attributeName,Double.class));
} else if (”String“.equalsIgnoreCase(type)) {
pstmt.setString(seq, BeanValueUtils.getValue(obj,attributeName,String.class));
} else if (”Date“.equalsIgnoreCase(type)) { // java.util.Date
pstmt.setDate(seq,new java.sql.Date().parse(BeanValueUtils.getValue(obj,attributeName,java.uitl.Date.class.getTime()));
} else {
pstmt.setNull(seq, Types.NULL); //不知道的类型
然后返回程序,跟上
PreparedStatementUtils.setPreparedStatement(x,pstmt,this.vo,this.columnsMap.get(x));,如果有异常就向上抛,就可实现。
4、如果要调用 getter 方法还需要有一个字符串的处理类,如下:
package cn.mldn.util;
public class StringUtils {
public static String initcap(String str) {
if (str == null ||””.equals(str)) {
return str ;
}
return str.substring(0,1).toUpperCase() + str.substring(1) ;
}
}
5、因为所有的操作里面都可能进行 PreparedStatement 的操作设置,那么就直接将其作为一个工具类,叫做
cn.mldn.util.dao.PreparedStatementUtils 类。
6、完成 AbstractDAO 类中的 createSupport()支持方法。
找到 AbstractDAO,调用
support.setPreparedStatement(pstmt);,再跟上 return pstmt.executeUpdate() > 0 ;,即可实现,
如下:
public boolean createSupport(Object vo) throws Exception {
CreateSupport support = new CreateSupport(vo) ;
this.pstmt = this.conn.preparedStatement(support.createSQL());
support.setPreparedStatement(pstmt);
return pstmt.executeUpdate() > 0 ;
}
}
执行后出现错误,所有的值都要保存知道集合里,但有一部分没有保存到集合里,序列号也不应该从1开始,改正后执行通过,也就是实现了vo自动创建SQL并自动保存到数据库的程序处理操作。数据库可通过反射来执行。
三、总结
整个的程序处理之中完全采用动态的解析模式完成,所以对于数据层的实现子类的调用就非常容易了如下:
public boolean doCreate(Member vo) throws Exception {
return super.createSupport(vo);
}
以后只要是单表处理操作,如果只都写一个 createSupport()就能够实现数据层保存。