java EE开发之Servlet第十一课:反射基础三

1 .使用反射机制形成通用sql语句

1)构建insert语句

public static void save(Object obj) {

// 获取传递过来对象的Class类对象

Class c = obj.getClass();

// 获取数据库连接

Connection conn = getConn();

// 准备执行SQL语句的对象(车、船)

PreparedStatement pstmt = null;

// 获取类对象的所有声明了的属性

Field[] fs = c.getDeclaredFields();

// 解锁

Field.setAccessible(fs, true);

// 根据获得的类对象,拼SQL语句

StringBuffer sb = new StringBuffer();

sb.append("insert into ");

// 表名

sb.append(c.getSimpleName());

sb.append(" values( ");

// 拼SQL语句有多少个问号

for (int i = 1; i < fs.length; i++) {

sb.append(" ? ");

if (i < fs.length - 1) {

sb.append(" , ");

}

}

sb.append(" ) ");

try {

// 初始化执行SQL语句的对象

pstmt = conn.prepareStatement(sb.toString());

// 给问号进行赋值

for (int i = 1; i < fs.length; i++) {

pstmt.setObject(i, fs[i].get(obj));

}

// 执行SQL语句

pstmt.executeUpdate();

} catch (SQLException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} finally {

closeAll(conn, pstmt, null);

}

System.out.println(sb);

}

2)构建select语句

public  List queryFX(Class clazz) {

List list = new ArrayList();

// 获取传递过来对象的类对象

//Class c = obj.getClass();

Connection conn = getConn();

PreparedStatement pstmt = null;

ResultSet rs = null;

// 获取声明的属性

Field[] fs = clazz.getDeclaredFields();

// 解锁

Field.setAccessible(fs, true);

// 拼SQL

StringBuffer sb = new StringBuffer();

sb.append(" select * from tbl_");

sb.append(clazz.getSimpleName());

// 初始化执行SQL语句的对象

try {

pstmt = conn.prepareStatement(sb.toString());

rs = pstmt.executeQuery();

// 从结果集中获取数据

while (rs.next()) {

// Student stu = new Student();

T o = (T) clazz.newInstance();

// stu.setSid(rs.getInt("sid"));

for (int i = 0; i < fs.length; i++) {

// 获取rs中的值

Object value = rs.getObject(fs[i].getName());

// 获value值存入到对应属性中xxx.setXxx();

if (value instanceof BigDecimal) {

// 将数据中类型为numeric类型的做一个和实体类型对应的转换

//value = ((BigDecimal) value).doubleValue();

value = ((BigDecimal) value).intValue();

}

/*

* if(value instanceof Timestamp ){

*      Timestamp ts =(Timestamp)value;

*      value = ts.toString();

* }

*/

// rs.getObject()获得的数据类型为时间戳类型

// 需要转换为实体中对应的java.sql.Date类型时,需要做以下转换

if (value instanceof Timestamp) {

Timestamp ts = (Timestamp) value;

value = new Date(ts.getTime());

}

// 把值装入到实体类中属性中

fs[i].set(o, value);

}

// 将对象放入到list中

list.add(o);

}

} catch (SQLException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} finally {

closeAll(conn, pstmt, rs);

}

return list;

}

注意: 表名和实体类名相同,表的列名和类的属性名一样。

总结:利用同样的思路,可以构建通用删除,通用更新,读者自行完成。

2 .克隆

1)普通属性不需要克隆

2) 浅度克隆:这个类中的属性没有引用另外一个类型的对象

该类必须显示的继承Object类和实现Cloneable接口,然后重写clone();就是把我们要克隆的类,实现一个Cloneable的接口,接口中无方法,只是一个标识 而已,然后写一个方法public void clone();本来是protected的,要改为public 的,这样才能在非子类中访问该方法,在main方法中,生成该类的两个对象,第一个 给他赋值,第二个就让它等于第一个对象的clone方法,这样就克隆了,第二个对象的改变不会影响第一个。

public class GrilFriend implements Cloneable {

........

@Override

public Object clone() throws CloneNotSupportedException {

// TODO Auto-generated method stub

return super.clone();

}

}

3)深度克隆:这个类中的属性有引用另外一个类型的对象

浅克隆,只涉及到一个类的克隆;既然有浅克隆也就有深克隆,深克隆,是指:在第一个类中用到了另外的类作为属性,那样的话,当第一个类要克隆,则它所涉及的类则都要标识为克隆的,并实现从clone方法。

@Override

//procted-->public

public  Object clone() throws CloneNotSupportedException {

//调用父类的克隆方法

//称为浅度克隆

//return super.clone();

//做深度克隆

//把用户克出来

Users u  = (Users)super.clone();

//把用户女友克出来

GrilFriend gf= (GrilFriend)u.getGf().clone();

//绑定用户的克隆的对象和女友有克隆对象

u.setGf(gf);

return u;

}

3.序列化

1)序列化作用:

当我们在电脑上玩游戏等一些事情时,然而有时我们要去有事,而此时我们退出游戏,

会有一个是否保存当前游戏的按钮,保存的是我们当前游戏的状态,例如:当前自己的位置,怪物的位置等等。

而这时我们就可以用到序列化来解决这个问题

2)序列化是什么:

就是指把java生成的一个对象(包括属性和方法),以一种对象输出流(ObjectOutputStream)的方式,写入到硬盘的文件中(writeObject(Object obj)),以后要使用到这个对象,也可以用对象输入流(ObjectInputStream)的方式读到程序中,使用(readObject())把文件中的内容恢复为一个对象,恢复的对象的数据与当初写入对象的数据一至,这样对像就可以在网络中传输,以及像游戏那样得到自己的位置,怪物的位置等等

3)怎么实现序列化

(1)需要序列化的类必须实现Serializable,但没有方法需要实现,它只是一种标示,标示该类可以序列化

(2)建立FileOutputStream,写到哪个文件里,再套用ObjectOutputStream,调用writeObject(Object o)序列化对象

(3)建立FileInputStream,读硬盘的文件,再套用ObjectInputStream,调用readObject()恢复对象

(4)可以同时写多个对象进去,那么每个对象都会给它一个标志位,用来区别,读的时候先进去先出来,后进去后出来(队列结构)

(5)static和transient是不能默认序列化,就是指凡是它们修饰的属性的值不会序列化到文件里面去,那么读出来也是为空的

(6)可以通过重写Serializable接口已经注释的方法

writeObject(ObjectOutputStream out)来序列化static和 transient修饰的属性的值,通过readObject(ObjectInputStream in),来读static和 transient修饰的属性的值这两个方法必须是private void 的,在序列化对象和读对象的时候jdk会自动去调用这两个方法,有一些注意事项看代码

完整代码

public class Users implements Serializable{

.........

//序列化时,static和transient(瞬时态)修饰的变量,不可序列化

private static String email;

private transient String phone;

序列化

Users users = new Users();

users.setUid(1);

users.setUname("tom");

users.setAge(24);

users.setPhone("13888888");

users.setEmail("[email protected]");

try {

//创建对象输出流

ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("users.txt"));

os.writeObject(users);

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

反序列化

try {

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users.txt"));

Users users = (Users)ois.readObject();

System.out.println(users.getUid()+"/t"+users.getUname());

System.out.println(users.getPhone()+"/t"+users.getEmail());

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

版权声明:
作者:siwei
链接:https://www.techfm.club/p/44431.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>