开发者学堂课程【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
要进行增加数据处理的V
O
类对象
* @
return
增加成功返回true,否则返回false
*
/
public
boolean
createSupport(
O
bject
vo
) {
return
false
;
}
2、既然要实现追加数据操作,就建议有一个单独类去实现;
· 创建一个 cn.mldn.util.dao.support.InsertSupport 类,将 Insert 写为 Create 也可以,如下:
package
cn
.mldn.util.dao.support
;
/
**
*
此类主要完善增加操作的Prepared
S
tatement内容设置、更新执行以及S
QL
语句创建
* @
author
mldn
*
*
/
public
class
C
reate
S
upport
{
}
如果想要创建的时候,需要有补充位。如果要想追加控制,整个过程要交给
CreateSupport support = new CreateSupport();,在这里进行对对象的操作控制。
在位中应该通过 public
S
tring
create
SQL
(
) {}
方法进行操作。而最关键的问题是很多都需要 createSQL(),可以将其变为接口进行操作。
此时要求传入 Object vo,即 public
S
tring
create
SQL
(
O
bject
vo
) {}
,从而要创建增加数据的 SQL 语句。如果要创建,就要进行大量的修改,一旦要进行修改,就要通过 String
B
uffer
buf
=
new
String
B
uffer()
;,再进行跟上 return buf.toString() ;来进行操作。
此时要进行追加,追加的语句为 Insert
INTO membe
r(mid,name,age,phone,birthday,note)
VALUES
(?
,?,?,?,?,?)
,类名称可以通过String
table
N
ame
=
vo
.
get
C
lass(
).getSimpleName();
来取得,类名称即为表名称。
如果表名称与类名称不一致,再加配置文件,将二者对在一起。
完成以上操作后,再通过代码
String
id
C
olumn
= R
esource.
getId
(
vo.getClass.getName());
取得主键,取得主键列后问号也同时产生,所以要有两个StringBuffer,一个是用来控制列,另一个是用来控制问号的,而且要记录好第一个问号是mid,
第二个问号是 name,否则无法设置值。所以在代码中增加 Map ,即P
rivate
M
ap<
I
nteger,String>
columns
M
ap
=
new
H
ashMap<
I
nteger,String>(
) ;
从而用来定义序号以及列名称的关系,有了名字就可以操作其中的属性内容。
然后在代码中添加 bufHead 和 bufTail ,即表示为 String
B
uffer
buf
H
ead
=
new
String
B
uffer()
;和String
B
uffer
buf
T
ail
=
new
String
B
uffer();
,这时还需要一个总的 buf,即String
B
uffer
buf
=
new
String
B
uffer()
;。写入代码buf.
append(“INSERT INTO”).
append(table
N
ame).
append(“)”)
;。
取得主键列名称,即追上代码
buf
H
ead.
append(“idColunm”) .append(“,”)
,
再追加bufTail.
append(“?”).append(“,”);,
表示为追加主键列的“?”。追加columns
M
ap.
put(1,idColumn) ;
以便用来保存对应关系。随后需要取出所有的其他字段的对应关系,但是这些关系里面不应该再包含有主键列。
再跟上Field
voFields
[
] = vo.getClass
(
).getDEclaredFields();
,取得全部的名称,再依次将内容保存到集合里面,同时生成 SQL 语句。
再跟上for(
int x = 0 ; x < voFields.length ; x++
)
{,然后进行判断,即
if(!idColumn.
equals(voFields[x].getName()))
{
,如果不一样,表示属性不是主键列,那么现在就可以实现操作。
要先进行保存,即
buf
H
ead.
append(voFields[x].getName()).append(“,”);
,再进行追加buf
T
ail.
append(“?”).append(“,”) ;,
处理完成之后,要实现最后的 SQL 拼凑,即要先追加
bufHead.
delete(bufHead.length()-1, bufHead.length());,
再跟上
buf
T
ail.
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. createS
u
pport(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(PreparedStatemen
t,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
get
V
alue(
O
bject
obj,String,attributeName,Class<
T> cls) {
try {
Method getMethod =
obj.getClass().getMethod(“get” +
StringUtils.initcap(attributeName)) ;
r
eturn getMethod.invoke(obj) ;
}
catch(Exception
e) {
e.
printStackTrace();
}
r
eturn null ;
}
}
也是可以被重复调用的位。下面的处理采用 for 循环,有多少个属性就循环多少次,所以跟上 for(int
x
= 1
;x
<= columnsMap.size() ; x ++)
{,然后设置内容,但要按照属性操作过于麻烦。如果想开发框架,如下:
package
cn
.
mldn.util.
dao;
p
ublic class PreparedStatementUtils {
private PreparedStatementUtils
(
) {}
/
**
*
设置指定序号的Prepared
S
tatement的内容
* @param s
eq
序号
* @param pstmt
Prepared
S
tatement对象
* @param obj
要取得属性内容的对象
* @param attribute
属性的名称
*/
public static void set PreparedStatement(int seq,PreparedStatement pstmt,Object obj,String attribute) throws Exception {
S
tring
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 (”D
ate“.
equalsIgnoreCase(type)) {
/
/
java.
util.Date
pstmt.setDate(seq,new java.sql.Date().parse(BeanValueUtils.getValue(obj,attributeName,
j
ava.uitl.Date.class.getTime()));
} else {
pstmt.setNull(seq, Types.NULL); //
不知道的类型
然后返回程序,跟上
Prepared
S
tatement
U
tils.
set
Prepared
S
tatement
(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(
O
bject
vo
)
throws
E
xception
{
C
reate
S
upport
support
=
new
C
reate
S
upport(
vo) ;
this.
pstmt = this.conn.preparedStatement
(support
.createSQL()
);
support.
setPreparedStatement(pstmt);
return
pstmt.
executeUpdate() > 0 ;
}
}
执行后出现错误,所有的值都要保存知道集合里,但有一部分没有保存到集合里,序列号也不应该从1开始,改正后执行通过,也就是实现了vo自动创建SQL并自动保存到数据库的程序处理操作。数据库可通过反射来执行。
三、总结
整个的程序处理之中完全采用动态的解析模式完成,所以对于数据层的实现子类的调用就非常容易了如下:
public
boolean
do
C
reate
(Member
vo)
throws
E
xception
{
return
super.create
S
upport(
vo)
;
}
以后只要是单表处理操作,如果只都写一个 createSupport()就能够实现数据层保存。