1 .使用反射機制形成通用sql語句
1)構(gòu)建insert語句
public static void save(Object obj) {
// 獲取傳遞過來對象的Class類對象
Class c = obj.getClass();
// 獲取數(shù)據(jù)庫連接
Connection conn = getConn();
// 準備執(zhí)行SQL語句的對象(車何鸡、船)
PreparedStatement pstmt = null;
// 獲取類對象的所有聲明了的屬性
Field[] fs = c.getDeclaredFields();
// 解鎖
Field.setAccessible(fs, true);
// 根據(jù)獲得的類對象冯挎,拼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 {
// 初始化執(zhí)行SQL語句的對象
pstmt = conn.prepareStatement(sb.toString());
// 給問號進行賦值
for (int i = 1; i < fs.length; i++) {
pstmt.setObject(i, fs[i].get(obj));
}
// 執(zhí)行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)構(gòu)建select語句
public? List<T> queryFX(Class<T> clazz) {
List<T> list = new ArrayList<T>();
// 獲取傳遞過來對象的類對象
//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());
// 初始化執(zhí)行SQL語句的對象
try {
pstmt = conn.prepareStatement(sb.toString());
rs = pstmt.executeQuery();
// 從結(jié)果集中獲取數(shù)據(jù)
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值存入到對應(yīng)屬性中xxx.setXxx();
if (value instanceof BigDecimal) {
// 將數(shù)據(jù)中類型為numeric類型的做一個和實體類型對應(yīng)的轉(zhuǎn)換
//value = ((BigDecimal) value).doubleValue();
value = ((BigDecimal) value).intValue();
}
/*
* if(value instanceof Timestamp ){
*? ? ? Timestamp ts =(Timestamp)value;
*? ? ? value = ts.toString();
* }
*/
// rs.getObject()獲得的數(shù)據(jù)類型為時間戳類型
// 需要轉(zhuǎn)換為實體中對應(yīng)的java.sql.Date類型時输吏,需要做以下轉(zhuǎn)換
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;
}
注意: 表名和實體類名相同枢舶,表的列名和類的屬性名一樣。
總結(jié):利用同樣的思路幔欧,可以構(gòu)建通用刪除包警,通用更新,讀者自行完成伯顶。
2 .克隆
1)普通屬性不需要克隆
2) 淺度克隆:這個類中的屬性沒有引用另外一個類型的對象
該類必須顯示的繼承Object類和實現(xiàn)Cloneable接口,然后重寫clone();就是把我們要克隆的類,實現(xiàn)一個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)深度克虏阕埂:這個類中的屬性有引用另外一個類型的對象
淺克隆,只涉及到一個類的克碌篌稀破花;既然有淺克隆也就有深克隆,深克隆疲吸,是指:在第一個類中用到了另外的類作為屬性座每,那樣的話,當?shù)谝粋€類要克隆摘悴,則它所涉及的類則都要標識為克隆的峭梳,并實現(xiàn)從clone方法。
@Override
//procted-->public
public? Object clone() throws CloneNotSupportedException {
//調(diào)用父類的克隆方法
//稱為淺度克隆
//return super.clone();
//做深度克隆
//把用戶克出來
Users u? = (Users)super.clone();
//把用戶女友克出來
GrilFriend gf= (GrilFriend)u.getGf().clone();
//綁定用戶的克隆的對象和女友有克隆對象
u.setGf(gf);
return u;
}
3.序列化
1)序列化作用:
當我們在電腦上玩游戲等一些事情時蹂喻,然而有時我們要去有事葱椭,而此時我們退出游戲捂寿,
會有一個是否保存當前游戲的按鈕,保存的是我們當前游戲的狀態(tài)挫以,例如:當前自己的位置者蠕,怪物的位置等等。
而這時我們就可以用到序列化來解決這個問題
2)序列化是什么:
就是指把java生成的一個對象(包括屬性和方法)掐松,以一種對象輸出流(ObjectOutputStream)的方式踱侣,寫入到硬盤的文件中(writeObject(Object obj)),以后要使用到這個對象大磺,也可以用對象輸入流(ObjectInputStream)的方式讀到程序中抡句,使用(readObject())把文件中的內(nèi)容恢復為一個對象,恢復的對象的數(shù)據(jù)與當初寫入對象的數(shù)據(jù)一至,這樣對像就可以在網(wǎng)絡(luò)中傳輸杠愧,以及像游戲那樣得到自己的位置待榔,怪物的位置等等
3)怎么實現(xiàn)序列化
(1)需要序列化的類必須實現(xiàn)Serializable,但沒有方法需要實現(xiàn),它只是一種標示流济,標示該類可以序列化
(2)建立FileOutputStream锐锣,寫到哪個文件里,再套用ObjectOutputStream绳瘟,調(diào)用writeObject(Object o)序列化對象
(3)建立FileInputStream,讀硬盤的文件雕憔,再套用ObjectInputStream,調(diào)用readObject()恢復對象
(4)可以同時寫多個對象進去,那么每個對象都會給它一個標志位糖声,用來區(qū)別斤彼,讀的時候先進去先出來,后進去后出來(隊列結(jié)構(gòu))
(5)static和transient是不能默認序列化蘸泻,就是指凡是它們修飾的屬性的值不會序列化到文件里面去琉苇,那么讀出來也是為空的
(6)可以通過重寫Serializable接口已經(jīng)注釋的方法
writeObject(ObjectOutputStream out)來序列化static和 transient修飾的屬性的值,通過readObject(ObjectInputStream in)悦施,來讀static和 transient修飾的屬性的值這兩個方法必須是private void 的并扇,在序列化對象和讀對象的時候jdk會自動去調(diào)用這兩個方法,有一些注意事項看代碼抡诞。
完整代碼
public class Users implements Serializable{
.........
//序列化時拜马,static和transient(瞬時態(tài))修飾的變量,不可序列化
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 {
//創(chuàng)建對象輸出流
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();
}