hibernate學習筆記(二)

寫在前面的,很常用,現解釋如下

hibernate.cfg.xml爲hibernate的核心配置文件
sessionFactory 爲session工廠,對應數據庫的配置和連接信息
session 指的是和數據庫的一次會話(connection)


1.

<property name="gname" column="gname"></property>
<!-- column對應數據庫中的字段,可不寫 ,默認值爲屬性名-->
2.session.evict(obj)會將指定的對象從session緩存中清除。

session.clear():會把緩衝區的全部對象清除,但不包括操作中的對象。

3.映射文件中,<column name="myGrade_id">表示外鍵。

4.ThreadLocal是爲了解決多線程的併發問題而設計,把數據和線程綁定起來,無需加鎖。爲了減少衝突,給每一個請求都分配一個通道。類似於存儲東西的盒子,犧牲空間來減少時間的消耗。比如使用ThreadLocal後,把一個對象存入A線程,在B線程中查找對象的屬性,則找不到。
Thread並不是一個thread,而是thread的局部變量

5.inverse常用在一對多雙向關聯關係中,表示是否放棄外鍵維護權,true表示放棄,false表示不放棄。在一對多的表中,inverse只能用在one的這一方。即在一的這一方設置inverse=true,表示將主外鍵的關係交由多方來維護。這是爲了節約數據庫資源,打個比方,在一個公司,是所有員工認識老闆容易,還是老闆認識所有員工容易?
inverse屬性的作用爲是否將集合對象的修改反映到數據庫中,inverse的默認值爲false,表示將集合對象的修改反映到數據庫中,inverse=false的爲主動方,由主動方負責維護關聯關係。inverse=true,表示對集合對象的修改不會被反映到數據庫中。

6.Collection是最基本的java集合接口,Set、List都繼承了Collection,Map沒有。
Set是最簡單的一種集合,集合中的對象沒有順序,且不重複。Set接口主要實現了兩個類,HashSet和TreeSet
List集合中的對象有順序,且可以重複。接口實現了兩個類,ArrayList和LinkedList
Map沒有繼承Collection接口,它存儲的是鍵值對對象。

7.可以通過在HiberUtil中寫

System.out.println(facyoty.openSession()==null);//下邊這句也可以,這兩段是等價的
System.out.println(HiberUtil.getSession()==null);
來生成數據庫表,若爲false,表示可以生成數據庫。爲true則不能生成表。而HiberUtil爲

public class HiberUtil {
	private static SessionFactory factory;
	
	static{
		Configuration conf =  new AnnotationConfiguration().configure();//這裏與原生的hibernate不同
		factory = conf.buildSessionFactory();
	}
	
	public static Session getSession(){
		return factory.openSession();
	}
	
	public static void main(String[] args) {
		System.out.println(factory.openSession()==null);//通過該段代碼生成表
		//System.out.println(HiberUtil.getSession()==null);//這段代碼也可以生成表
	}
}
8.註解是一種配置,它和xml、properties文件作用類似,和註釋不一樣。
①註解是寫到java代碼中的鍵值對形式。
②String value是註解默認的書寫方式
③target用來說明註解可以放在哪些地方,retention說明註解的生命週期,最長的是runtime

9.關於反射的invoke()方法

Class c = Test.class();//Test爲一個java類
Object obj = c.newInstance();
Method m = c.getDeclaredMethod("say");
m.invoke(obj);//表示執行obj的say方法,只是用了反射,相當於倒過來寫
10.load和get方法,load有一個lazy屬性,表示延遲加載。比get少了無效操作,比如查詢數據庫時,lazy會延遲加載,load會返回一個假的對象,即代理對象。
get方法沒有懶加載問題,load方法有懶加載問題。
get先去session緩存中找,若沒有就去數據庫找,再沒有就返回null
load先去session緩存中找,若沒有就去數據庫找,再沒有就報異常

共同點就是都會先從一級緩存、二級緩存中去找,如果沒有才去數據庫找。

11.hibernate使用註解(annotation)步驟

①引入jar包,3個。ejb3-persistence,hibernate-annotations,hibernate-commons-annotations

②修改配置文件hibernate.cfg.xml,如原來的爲

<mapping resource="com/bjsxt/po/User.hbm.xml" /> <!--注意結束標記,否則報錯-->
則要修改爲

<mapping class="com.bjsxt.po.User" />
其它不變

③原來的Configuration也得換
原來的

Configuration conf = new Configuration.configue();
factory = conf.buildSessionFactory();
修改爲

Configuration conf =  new AnnotationConfiguration().configure();//該處發生變化
factory = conf.buildSessionFactory();
12.
⑴在many-to-many關係中,那邊可以設置mappedBy?

mappedBy作用是①放棄對外鍵的建立和維護②指定一個查詢通道
如果不寫mappedBy,那麼就會產生多重複的中間表,只是表名不同,表中字段相同。
原則就是,哪邊更新比較頻繁,哪邊就應該放棄外鍵的管理權。即寫上mappedBy="某個值",如Student和Couse表,student更新比較頻繁,則

/*********Student表***********/
@ManytoMany(mappedBy="students")
Set<Course> setCourse = new HashSet<Course>();

/*********Course表***********/
@ManytoMany
Set<Student> students = new HashSet<Student>();

⑵在one-to-many中,mappedBy的寫法。
如在Grade和User中,一個班級對應多個用戶
則mappBy放在one的一方(即在Grade中寫@OneToMany(mappedBy="grade")),表示Grade放棄外鍵管理權

/*********Grade表***********/
@OneToMany(mappedBy="grade")
private Set<User> set = new HashSet<User>();

/*********User表***********/
@ManyToOne
private Grade grade;

⑶在one-to-one中,則有
如Company和Address爲一對一,一個地址對應一個公司。mappedBy可置於任何一方,因爲是一一對應。
除了用
@OneToOne(mappedBy="company")
這種寫法外,還可以用

@ManyToOne
@JoinColumn(unique=true)
//這也可以用多對一,下邊用unique表示多的一方也是唯一的,整體還是表示一對一
13.xml中,lazy屬性默認都爲true,即都爲懶加載
註解中(annotation),則視情況而定。set集合爲lazy(懶加載),單個元素爲eager(不是懶加載)。懶加載歸根結底還是爲了節約資源。

14.hibernate中的註解釋義:

@Entity表示當前爲實體類
@Id 表示主鍵
@GeneratedValue 表示主鍵含義,默認表示自增,即主鍵爲自增列
@Column 映射字段的含義,包括映射的數據庫表的字段名稱、是否允許爲空、字段長度等。如:
@Column(name="id",unique=true,nullable=false,length=30)
//name:字段名稱
//unique:是否唯一
//nullable:是否可以爲空
//length:字段長度
這些字段除了name,都不是必須出現的。

15.hibernate.cfg.cml中的配置一定要寫好結束符,否則會報錯:
Could not parse configuration: /hibernate.cfg.xml.
如下邊的兩種結束方式都可以

<mapping class="com.bjsxt.po.Student"></mapping>
<mapping class="com.bjsxt.po.Course" />
而當出現這種錯誤是,可以先用瀏覽器打開該配置文件,瀏覽器會指出錯誤的位置。

16.在用註解生成數據庫表時,除了在實體類前標註@Entity外,一定要在hibernate.cfg.xml中導入相應的mapping class,如:

<mapping class="com.bjsxt.po.Company" />
否則雖然不報錯,但會生不成表。

17.在hibernate中,單個對象用uniqueResult()接收。集合一般用List接收。如

⑴單個對象

Session session = HiberUtil.getSession();
String hql = "select count(*) from Student";
Query query = session.createQuery(hql);
Number num = (Number) query.uniqueResult();//用Number類型接收,否則可能會由於long轉int出錯
int count = num.intValue();//再由Number轉化爲int
上述用Number類型接收,避免了可能由long轉int出現的錯

⑵集合

String hql = "slect new map(s.name as sname,s.tel as stel) from Student s";//注意hql寫法,map爲小寫,list裏存放的是map集合
//動態構造對象實例的方法,將數據封裝.但這裏的map封裝的只是name和tel屬性,不能進行更新操作
Query query = session.createQuery(hql);
List<Map<String,Object>> list = query.list();//雖然加入map,但還是由List接收整體
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
	Map<String, Object> map = (Map<String, Object>) iterator.next();
	System.out.println(map.get("sname") + "********" + map.get("stel"));
}
還可以用數組接收

String hql = "select s.name,s.tel from Student s";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();//主要還是看這塊的數組符號,list裏存放的是Object數組
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
	Object[] objects = (Object[]) iterator.next();//強制抓換也是用數組
	System.out.println((String)obj[0] + "******" + (String)obj[1]);
}
或者用自定義的類接收,即可以加入VO層(寫法和po中實體類差不多)

String hql = "select new com.bjsxt.vo.StudentVO(s.name,s.tel) from Student s";//注意hql寫法,list裏存放的是自定義類StudentVO,必須加包名。
//此時由於StudentVO要接收兩個參數,所以在StudentVO中,除了get和set方法,無參構造器外,還必須有這兩個參數的有參構造器。
 Query query = session.createQuery(hql);
List<StudentVO> list = query.list();
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
	StudentVO stu = (StudentVO) iterator.next();
	System.out.println(stu.getSname() + "********" + stu.getTel());
	//getSname()和getTel()爲StudentVO的方法
}
實際測試發現,這三種map和Object[],還有加入VO層的結果是一樣的。雖然hql語句不同。
18.hql語句中可以利用Query接口和順序佔位符“?”進行參數填充,如

String hql = "from TUser user where user.name=? and user.age>?";
Query query = session.createQuery(hql);
query.setString(0,"Erica");
query.setInteger(1, 20);
也可以利用佔位符填充參數

String hql = "from User where name=:name and pwd=:pwd";//注意該出的寫法,前邊有冒號
Query query = session.createQuery(hql);
query.setParameter("name","Erica");


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章