围绕这个来总结笔记
1.参数中的这个Objcet… 原来是个对象—[] 可读性不好
2.用户在使用的时候 传递参数还需要自己来指定顺序 用起来不是很方便 很舒服
3. 将那个恶心的参数设计回对象形式 Object… Atm
如何去处理原来SQL上面的问号 与 Atm对象中的属性 一一对应的问题
3.2.1开始
因为原先是数组的形式存储,那么用户传参数就需要按照顺序去传,这样可读性不好,用起来不方便,那么可以用对象来返回这样会比较好一点,如何处理SQL中的?问题呢需要一一对应。
例如SQL语句中有问号
insert into atm value(?,?,?);
这种有问号的需要我们自己去规定,然后在输入的时候进行匹配。可以用标识符去完成
insert into atm value(#{aname},#{apassword},#{abalance});
所以这样在进行JDBC流程的时候就需要先进行解析SQL语句,要不没办法进行赋值操作,找小弟去完成在找小弟之前需要解析sql最终的存储结果、 设计一个对象_ 对象的目的是为了解析SQL后用来存储最终结果的_ ArrayList 按顺序存放解析出来的全部key String
用来存放还原回去的那个原来的sql_
public class SQLAndArrlist {
private ArrayList<String> keyList = new ArrayList();<br /> private StringBuilder sql = new StringBuilder();//拼接时候性能更好
public SQLAndKey(ArrayList<String> keyList, StringBuilder sql) {<br /> this.keyList = keyList;<br /> this.sql = sql;<br /> }
public ArrayList<String> getKeyList() {<br /> return keyList;<br /> }<br /> public String getSQL() {<br /> return sql.toString();<br /> }
}
这是jdbc的小弟方法
SQLAndKey parseSQL(String sql){
//1.提供两个新的变量 用来分别存储解析后的两部分
ArrayList
StringBuilder newSQL = new StringBuilder();
//2.解析
//insert into atm values(#{aname},#{apassword},#{abalance} order by xxx)
while(true) {
//找寻#{ }的位置找寻索引位置,按照这个位置进行拆然后拼接
int left = sql.indexOf(“#{“);
int right = sql.indexOf(“}”);
//严谨的判断
if (left != -1 && right != -1 && left < right) {
//找到了一组#{} 截取中间的key
newSQL.append(sql.substring(0, left));//前半部分 保留
newSQL.append(“?”);中间转换成?的形式给jdbc
keyList.add(sql.substring(left + 2, right));
}else{//sql中已经没有成组的#{}啦
newSQL.append(sql);
break;
}
sql = sql.substring(right+1);
}
//将两个变量组合成一个对象 返回
return new SQLAndKey(keyList,newSQL);
}
然后可以进行拼接将所有的key拿到,找寻对应的obj对应的类型,但是obj类型不一定是什么类型,拼接的方式也就不同,所以需要设计一个方法帮助pstat完成拼接
void helppstat(PreparedStatement pstat,Object obj,ArrayList
//获取obj对应的那个Class类
Class clazz = obj.getClass();
clazz通常应该是什么类型的
就是基础类型 int—Integer float—Float double—Double String
就是domain类型 atm student
if(clazz==int.class || clazz==Integer.class){
pstat.setInt(1,(Integer)obj);
}else if(clazz==float.class || clazz==Float.class){
pstat.setFloat(1,(Float)obj);
}else if(clazz==double.class || clazz==Double.class){
pstat.setDouble(1,(Double)obj);
}else if(clazz==String.class){
pstat.setString(1,(String)obj);
}else if(clazz.isArray()){
不支持这个类型,这个不行
}else{
//剩下的只有两种可能
if(obj instanceof Map){//1.map
this.setMap(pstat,obj,keyList);
}else{//2.domain
this.setObject(pstat,obj,keyList);
}
}
}
//一个小小弟 负责帮助上面那个helppstat方法拼接map类型
private void setMap(PreparedStatement pstat,Object obj,ArrayList
Map map = (Map)obj;
for(int i=0;i
}
}
//另一个小小弟 负责帮助下面那个helppstat方法拼接对象
private void setObject(PreparedStatement pstat,Object obj,ArrayList
try {
通过反射拿到atm这个类
Class clazz = obj.getClass();//atm
for (int i = 0; i < keyList.size(); i++) {
每次循环找到一个key
String key = keyList.get(i);
通过key去obj对象中获取属性通过反射
Field field = clazz.getDeclaredField(key);
直接操作私有属性,true获取这个操作的权限
field.setAccessible(true);
获取属性值
Object value = field.get(obj);
交给pstat存入即可
pstat.setObject(i+1,value);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
接下来执行JDBC流程就行
public void update(String sql,Object obj){
try {
//0.SQL解析
SQLAndKey sqlAndKey = handler.parseSQL(sql);
//1.加载驱动
Class.forName(className);
//2.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//3.创建状态参数(sql)
PreparedStatement pstat = connection.prepareStatement(sqlAndArrlist.getSQL());
//4.将SQL和那些值拼接在一起
if(obj!=null){
handler.handleParameter(pstat,obj,sqlAndArrlist.getKeyList());
}
//5.执行executeUpdate操作
pstat.executeUpdate();
//6.关闭资源
pstat.close();
connection.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
总结:
主要是解决问号顺序固定的规则,通过解析sql语句将语句中的具体值存入arraylist中,然后通过数组返回问号的形式,在拼接的过程中解决object有可能包含的类型的问题。