※刪除
Session session = HibernateUtil2.getSession();
try {
Query hqlDelete = session.createQuery(" delete from Dept where deptno = :deptno");
hqlDelete.setParameter("deptno", 60);
int rtn = hqlDelete.executeUpdate();
if(rtn > 1){
System.out.println("刪除成功!");
} else {
System.out.println("無資料可刪除!");
}
} catch (Exception e) {
System.err.println("例外錯誤!");
e.printStackTrace();
} finally {
session.close();
}
※因為hibernate是資料庫和物件的轉換,而HQL是物件的操作,所以必需注意Dept大小寫要和hbm.xml的java類名稱一致,否則會出「xxx is not mapped」的錯誤
※刪除時,from可以不寫
※hibernate-mapping有個屬性auto-import,預設是true,所以Dept才可以不用寫包.類,但如果有兩個以上都是同名,還是會報錯,還有另一種方法,就是使用別名
Dept.hbm.xml
<hibernate-mapping> <import class="vo.Dept" rename="xxx"/> <class> <!-- ... --> </class> </hibernate-mapping>
※這時就可以使用xxx代替Dept了(class一定要包.類),但別名如果和其他的class同名(cfg.xml有設定mapping resource或mapping class),而且auto-import是true或沒設,假設我打Emp,這時就會出「duplicate import: Emp refers to both vo.Dept and vo.Emp (try using auto-import="false")」的錯
※修改
Session session = HibernateUtil2.getSession();
try {
Query hqlUpdate = session.createQuery(" update Dept set dname = ?, loc = :loc where deptno = 60 ");
hqlUpdate.setString(0, "IT");
hqlUpdate.setString("loc", "zh_CN");
int rtn = hqlUpdate.executeUpdate();
if(rtn > 1){
System.out.println("修改成功!");
} else {
System.out.println("無資料可修改!");
}
} catch (Exception e) {
System.err.println("例外錯誤!");
e.printStackTrace();
} finally {
session.close();
}
※Query有很多的setXxx可以用,還可以像刪除那樣,用setParameter,會自動偵測
※Query的第一個參數可用數字或字串,數字從0開始,字串必須對應「:字串」,也可以混用
※混用時必須注意數字(也就是?)必須在字串前面,不然會出「cannot define positional parameter after any named parameters have been defined」的錯
※新增
Session session = HibernateUtil2.getSession();
try {
Query hqlInsert = session.createQuery(" insert into Dept(deptno, dname, loc) select 60, 'IT', 'zh_TW' from Emp where empno = 7369 ");
int rtn = hqlInsert.executeUpdate();
if(rtn > 1){
System.out.println("新增成功!");
} else {
System.out.println("無資料可新增!");
}
} catch (Exception e) {
System.err.println("例外錯誤!");
e.printStackTrace();
} finally {
session.close();
}
※新增不支援values的寫法,這裡的最後一張圖,往上一點點,only開頭的有寫
可能是hibernate一定要先查詢才有辦法做到吧!
※新增時不能用setXxx,像我是寫死的,這個例子舉的不好
※所以大部分新增都是用save()或者是Session的createSQLQuery()達成
※createSQLQuery(),裡面的SQL就是怕hibernate的功能不能達到時,可以根據各家的SQL進行撰寫,而且還加入一些較特殊的用法
※查詢
Session session = HibernateUtil2.getSession();
try {
Query hqlQuery = session.createQuery(" from Dept ");
List<?> list = hqlQuery.list();
for(Object o:list){
Dept d = (Dept) o;
System.out.println(d.getDeptno());
}
} catch (Exception e) {
System.err.println("例外錯誤!");
e.printStackTrace();
} finally {
session.close();
}
※不能寫select *,會說「*」是不認識的字元
※from Dept 等同 select d from Dept d
※List<Object>會出黃黃的警告,所以我用List<?>
※取特定的欄位
Query hqlQuery1 = session.createQuery(" select dname from Dept ");
List<?> list = hqlQuery1.list();
for(Object o:list){
System.out.println(o);
}
Query hqlQuery2 = session.createQuery(" select deptno, dname, loc from Dept ");
@SuppressWarnings("unchecked")
List<Object[]> list = hqlQuery2.list();
for (Object[] oArray : list) {
for (Object o : oArray) {
System.out.println(o);
System.out.println("-----");
}
}
※所以只有一個欄位回傳的是List<Object>;
多個欄位就是List<Object[]>,官方說一條結果返回多個物件叫tuples
※尤於沒有List<?[]>,因為?是什麼都不知道了,怎麼可能還有陣列,所以只好寫List<Object[]>
※將欄位轉換成VO物件
Query hqlQuery = session.createQuery(" select deptno as deptno, dname as dname, loc as loc from Dept ");
hqlQuery.setResultTransformer(new AliasToBeanResultTransformer(Dept.class));
List<?> list = hqlQuery.list();
Iterator<?> it = list.iterator();
while(it.hasNext()){
Dept d = (Dept) it.next();
System.out.println(d.getDname());
}
※雖然select的欄位名稱和vo物件一樣,但還是要「as欄位名」,連as都要打,as能省略的只有物件名,如from Dept d,如果不打會出「PropertyNotFoundException: Could not find setter for 0 on class vo.Dept」的錯
※將SQL或HQL分離
※XML設定
hbm.xml
<class name="vo.Dept" table="DEPT"> <!-- ... --> </class> <query name="xxx">from Dept</query> <sql-query name="ooo">SELECT * FROM DEPT</sql-query>
※query name為hql,類似createQuery(); sql-query為sql,類似createSQLQuery()
TestHibernate.java
Query hqlQuery = session.getNamedQuery("xxx");
List<?> listXxx = hqlQuery.list();
for(Object o:listXxx){
Dept d = (Dept)o;
System.out.println(d.getDname());
}
Query sqlQuery = session.getNamedQuery("ooo");
List<Object[]> listOoo = sqlQuery.list();
for(Object[] oArray:listOoo){
for(Object o:oArray){
System.out.println(o);
}
}
※Annotation設定
Dept.java@NamedQueries({ @NamedQuery(name = "xxx", query = "from Dept") })
@NamedNativeQueries({ @NamedNativeQuery(name = "ooo", query = "SELECT * FROM DEPT", resultClass=Dept.class) })
@Entity
@Table(name = "DEPT", schema = "c##scott")
public class Dept {
//...
}
※sql一定要加resultClass,不然執行時會報「org.hibernate.cfg.NotYetImplementedException: Pure native scalar queries are not yet supported」的錯; 而hql不用,也沒這個選項可設定
TestHibernate.java
Query query = session.getNamedQuery("ooo");
List<?> list = query.list();
for(Object o:list){
Dept d = (Dept)o;
System.out.println(d.getDname());
}
※用Annotation時輸出的結果,統一都用hql的寫法才不會報強制轉換的錯誤
※回傳只有一筆
Query hql = session.createQuery(" from Dept where deptno = 20 ");
Dept dept1 = (Dept) hql.list().get(0);
Dept dept2 = (Dept) hql.uniqueResult();
System.out.println(dept1.getDname());
System.out.println(dept2.getDname());
※使用uniqueResult()看起來較方便
※分頁
Query hql = session.createQuery(" from Emp ");
hql.setFirstResult(2);//從第幾筆開始
hql.setMaxResults(3);//一頁顯示幾筆
System.out.println("從0開始,機器的角度");
Iterator<?> it1 = hql.list().iterator();
while (it1.hasNext()) {
Emp e = (Emp) it1.next();
System.out.println(e.getEmpno());
}
System.out.println("從1開始,人的角度");
Iterator<?> it2 = hql.iterate();
while (it2.hasNext()) {
Emp e = (Emp) it2.next();
System.out.println(e.getEmpno());
}
※資料庫的內容
第一個迴圈的結果為: 7521、7566、7654
第二個迴圈的結果為: 7499、7521、7566
※工作時常這樣用
※機器角度的算法:int currentPage = 3;//模擬前端輸入第幾頁
int pageSize = 3;
Query hql = session.createQuery(" from Emp ");
hql.setFirstResult((currentPage - 1) * pageSize);//公式
hql.setMaxResults(pageSize);
Iterator<?> it1 = hql.list().iterator();
while (it1.hasNext()) {
Emp e = (Emp) it1.next();
System.out.println(e.getEmpno());
}
※注意setFirstResult的算法
結果為: 7782、7788、7839
人角度的算法:
int currentPage = 3;//模擬前端輸入第幾頁
int pageSize = 3;
Query hql = session.createQuery(" from Emp ");
hql.setFirstResult(currentPage * pageSize - pageSize + 1);//公式
hql.setMaxResults(pageSize);
Iterator<?> it2 = hql.iterate();
while (it2.hasNext()) {
Emp e = (Emp) it2.next();
System.out.println(e.getEmpno());
}
結果當然還是和上面一樣
如果在一級或二級快取已有資料,那iterate()比list()快,否則較慢


沒有留言:
張貼留言