1 .使用反射机制形成通用sql语句
1)构建insert语句
public static void save(Object obj) {
Class c = obj.getClass();
Connection conn = getConn();
PreparedStatement pstmt = null;
Field[] fs = c.getDeclaredFields();
Field.setAccessible(fs, true);
StringBuffer sb = new StringBuffer();
sb.append("insert into ");
sb.append(c.getSimpleName());
sb.append(" values( ");
for (int i = 1; i < fs.length; i++) {
sb.append(" ? ");
if (i < fs.length - 1) {
sb.append(" , ");
}
}
sb.append(" ) ");
try {
pstmt = conn.prepareStatement(sb.toString());
for (int i = 1; i < fs.length; i++) {
pstmt.setObject(i, fs[i].get(obj));
}
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
2)构建select语句
public List<T> queryFX(Class<T> clazz) {
List<T> list = new ArrayList<T>();
Connection conn = getConn();
PreparedStatement pstmt = null;
ResultSet rs = null;
Field[] fs = clazz.getDeclaredFields();
Field.setAccessible(fs, true);
StringBuffer sb = new StringBuffer();
sb.append(" select * from tbl_");
sb.append(clazz.getSimpleName());
try {
pstmt = conn.prepareStatement(sb.toString());
rs = pstmt.executeQuery();
while (rs.next()) {
T o = (T) clazz.newInstance();
for (int i = 0; i < fs.length; i++) {
Object value = rs.getObject(fs[i].getName());
if (value instanceof BigDecimal) {
value = ((BigDecimal) value).intValue();
}
if (value instanceof Timestamp) {
Timestamp ts = (Timestamp) value;
value = new Date(ts.getTime());
}
fs[i].set(o, value);
}
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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
注意: 表名和实体类名相同,表的列名和类的属性名一样。
总结:利用同样的思路,可以构建通用删除,通用更新,读者自行完成。
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 {
return super.clone();
}
}
3)深度克隆:这个类中的属性有引用另外一个类型的对象
浅克隆,只涉及到一个类的克隆;既然有浅克隆也就有深克隆,深克隆,是指:在第一个类中用到了另外的类作为属性,那样的话,当第一个类要克隆,则它所涉及的类则都要标识为克隆的,并实现从clone方法。
@Override
public Object clone() throws CloneNotSupportedException {
Users u = (Users)super.clone();
GrilFriend gf= (GrilFriend)u.getGf().clone();
u.setGf(gf);
return u;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
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{
.........
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("aa@qq.com")
try {
//创建对象输出流
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("users.txt"))
os.writeObject(users)
} catch (FileNotFoundException e) {
e.printStackTrace()
} catch (IOException e) {
e.printStackTrace()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
反序列化
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()
}