Hibernate
一.關(guān)系映射
1.單表映射:a. public class User { private Integer id;
private String name; get/set}
b.xml: <class name="User" table="user">
<id name="id" column="id" type="integer">//配置主鍵的生成方式
<generator class="identity"></generator> </id>
<property name="name" column="name" type="string"></property> </class>
c. hibernate.cfg.xml配置相應(yīng)數(shù)據(jù)庫和映射, show_sql=true;使console的sql語句可見
d.采取junit進行測試:一般通過junit的setUp方法初始化,通過tearDown釋放資源,自動加載
public class Client extends TestCase { protected Session session;
public Client(String name) { super(name); }
protected void setUp() throws Exception {
Configuration config=new Configuration().configure();//創(chuàng)建Hibernate配置管理類,默認加載cfg.xml,若改名則用configure(new File(“src/hib.cfg.xml”));加上路徑
SessionFactory sessionFactory =config.buildSessionFactory();
session= sessionFactory.openSession(); } //是application和Hibernate交互接口
protected void tearDown() throws Exception {if(session!=null) session.close();}
public void testCreate(){User user=new User();user.setName("hello");//自動加載
Transaction tr=null;//改變數(shù)據(jù)庫數(shù)據(jù)的操作都要開啟一個事物
try{ tr=session.beginTransaction(); session.save(user); tr.commit(); }
catch(HibernateException e) { //將自由狀態(tài)變成持久狀態(tài)
e.printStackTrace(); } if(tr!=null) tr.rollback(); }
public void testRetrieve(){
User user=(User)session.get(User.class, 122);//得到xml中的主鍵對應(yīng)的對象
assertEquals("hello", user.getName());}//使用斷言精確判斷,防止空格等因素
public static Test suite(){ //junit的靜態(tài)測試方法
TestSuite ts=new TestSuite(); Client cl=new Client("testCreate");
ts.addTest(cl); return ts; } }
e.session的load和get方法的區(qū)別:1.對象存在時,load返回實體代理類類型,get返回實體類
2.對象不存在時:load拋出異常,get返回null(用于判斷)
f.實體對象的生命周期
1.Transient自由狀態(tài):與Hibernate和數(shù)據(jù)庫沒有任何關(guān)系
2.Persistent持久狀態(tài):納入了Hibernate的Session實體對象管理的容器,session會復(fù)制實體對象的引用并進行臟數(shù)據(jù)檢查,實體對象任何狀態(tài)的改變最終都會同步到數(shù)據(jù)庫。例如:Transaction trx=null;
trx=session.beginTransaction(); User user=(User)session.load(User.class, 1);
user.setName("nihao"); trx.commit();
// session.update(user);就不需要了
3.Detached游離狀態(tài):(session.close()),與Hibernate和數(shù)據(jù)庫沒有任何關(guān)系,但是實體對象對應(yīng)數(shù)據(jù)庫的一條紀(jì)錄。如:trx=session.beginTransaction();
User user=new User(); user.setId(61);只要一個主鍵與數(shù)據(jù)庫唯一標(biāo)識
session.delete(user);//進行臟數(shù)據(jù)檢查 trx.commit(); //真正執(zhí)行
2.Generator的主鍵產(chǎn)生方式:
a. <generator class="assigned"></generator>由應(yīng)用邏輯產(chǎn)生:***.setId(number);
b.hilo:通過hi/lo(hign/low)算法產(chǎn)生
c.seqhilo:適合oracle沒有自動增長只有序列,主鍵歷史狀態(tài)保存在sequence中
d.increment:按照數(shù)值順序增長,由Hibernate維護,效率很高
e.identity:采用數(shù)據(jù)庫提供的主鍵生成機制,并發(fā)性不好
f.sequence:支持oracle這種數(shù)據(jù)庫
g.native:根據(jù)數(shù)據(jù)庫適配器自動采用identity,hilo,sequence中的一種
h.uuid:由Hibernate基于128位唯一算法生成32位字符串作為主鍵,適合所有數(shù)據(jù)庫,并發(fā)好
i:foreign:使用外部表的字段作為主鍵
3.一對一通過主鍵關(guān)聯(lián)(one to one)(數(shù)據(jù)庫中將兩個表id為主鍵并建立外聯(lián),只一表自動增長)
a. public class User1 { private Integer id; private String name;
private Passport passport; ...getter/setter} //將passport最為成員屬性
b. public class Passport { private Integer id; private String serial;
private User1 user; ...getter/setter} //將user作為成員屬性
c. <hibernate-mapping package="OneToOne"> <class name="User1" table="user1">
<id name="id" column="id" type="integer"> <generator class="identity"/></id>
<property name="name" column="name"></property> // type可以省略,由Hib匹配
<one-to-one name="passport" cascade="all" fetch="join"></one-to-one> </class>
</hibernate-mapping>//cascade主控方設(shè)置級聯(lián)同步更新,delete,sava-update,none
d. <hibernate-mapping package="OneToOne"> <class name="Passport" table="passport">
<id name="id" column="id"> <generator class="foreign"> //主鍵有外表產(chǎn)生
<param name="property">user</param> </generator> </id> //值來自user成員屬性
<property name="serial" column="serial"></property>
<one-to-one name="user" class=”更好”> </one-to-one></class> </hibernate-mapping>
e.要想實現(xiàn)級聯(lián)操作,要讓級聯(lián)雙發(fā)都知道對方的存在:
passport.setUser(user); user.setPassport(passport);
tr=session.beginTransaction();session.save(user); tr.commit();//才會起作用
4.通過外鍵關(guān)聯(lián):many to one(環(huán)境:很多個人在一個組中且fk:user.group_id-àgroup.id)
a. public class Group { private Integer id; private String name; }
b. public class User2 { private Integer id; private String name;
private Group group; ...getter/setter;}
c. <hibernate-mapping package="ManyToOne">
<class name="Group" table="group"> <id name="id" column="id">
<generator class="identity"></generator> </id>
<property name="name" column="name"></property> </class> </hibernate-mapping>
d. <hibernate-mapping package="ManyToOne"> <class name="User2" table="user2">
<id name="id" column="id"> <generator class="identity"/> </id>
<property name="name" column="name"></property>
<many-to-one name="group" column="group_id" fetch="join"></many-to-one>
</class> </hibernate-mapping> //關(guān)系由many端進行維護
e.關(guān)聯(lián)雙方:Group group=new Group(); group.setId(1); User2 user=new User2(); user.setName("hello"); user.setGroup(group); //session.save()才行
5.ont to many:(環(huán)境:一個人有多個地址,fk:address.user_idàuser.id)
a. public class MyUser { private Integer id; private String name;
private Set<Address> addresses; } //對應(yīng)多個值采用集合形式
b. public class Address { private Integer id; private String address;
private MyUser user; }
c. <hibernate-mapping package="ManyToOne"> <class name="MyUser" table="myuser">
<id name="id" column="id"> <generator class="identity"/> </id>
<property name="name" column="name"></property>
<set name="addresses" cascade="all" inverse="true" order-by="address asc" fetch="join"> <key column="user_id"></key> //必須通過外表的外鍵建立的關(guān)聯(lián)
Inverse=”true”進行反轉(zhuǎn),由many端來維護關(guān)聯(lián)
<one-to-many class="Address"/> </set> </class> </hibernate-mapping>
d. <hibernate-mapping package="ManyToOne"> <class name="Address" table="address">
<id name="id" column="id"> <generator class="identity"/> </id>
<property name="address" column="address"></property>
<many-to-one name="user" column="user_id"></many-to-one> </class> </hibernate-mapping>
e.使用時要設(shè)置關(guān)聯(lián):MyUser user=new MyUser();user.setName(“hello”);
Set<Address> addresses=new HashSet<Address>();
Address add1=new Address();add1.setZipcode(“241000”);
add1.setUser(user); addresses.add(add1); user.setAddresses(addresses);
二.HQL:特點:語法類似sql,使用面向?qū)ο蟮姆庋b,直接返回對象或?qū)ο髷?shù)組
1.查詢整個實體對象(不加select)
String hql="from com.mypack.User4"; Query query=session.createQuery(hql);
List lists=query.list(); for(int i=0;i< lists.size();i++){
User4 user=(User4)lists.get(i); System.out.println(user.getId()); }
或者: for(Iterator iter=users.iterator();iter.hasNext();){
User4 user=(User4)iter.next(); }
2.查詢單個屬性(返回單個屬性類型): hql="select u.name from User4 u";
query=session.createQuery(hql); List names=query.list();//執(zhí)行查詢
for(int i=0;i<names.size();i++){ String name=(String)names.get(i); }
3.1查詢多個屬性返回對象數(shù)組的集合: hql="select u.name,u.age from User4 u";
query=session.createQuery(hql); List names=query.list();//一步步轉(zhuǎn)型
for(int i=0;i<names.size();i++){ Object[ ] object=(Object[])names.get(i);
String name=(String)object[0]; Integer age=(Integer)object[1];
3.2也可以將多個屬性用單個屬性替代: hql="select new User4(u.name,u.age) from User4 u";
query=session.createQuery(hql); List names=query.list();
for(int i=0;i<names.size();i++){ User4 user=(User4)names.get(i); }
注:需要在User4中添加User4(name,age)構(gòu)造函數(shù),同時添加無參構(gòu)造函數(shù)防止影響其他代碼
4.聚合函數(shù)也可以使用: hql="select count(*) from User4 u";
query=session.createQuery(hql); int count=(Integer)query.list().get(0);
System.out.println(count);
當(dāng)確定只有唯一的一個結(jié)果: int count=(Integer)query.uniqueResult(); 代替
5.更新(需要加上Transaction): Transaction tr=session.beginTransaction();
hql="update User4 u set u.name='liming'";
query=session.createQuery(hql); query.executeUpdate(); tr.commit();
6.刪除操作: Transaction tr2=session.beginTransaction();
hql="delete from User4 u where u.id=81";
query=session.createQuery(hql); query.executeUpdate(); tr2.commit();
7.1.?查詢綁定: hql="from User4 u where u.name=?";
query=session.createQuery(hql); query.setString(0, "lm"); List user= query.list();
7.2.引用占位符:查詢綁定: hql="from User4 u where u.name=:name and u.id=:id";
query=session.createQuery(hql);
query.setInteger("id", 84); query.setParameter("name", "lm");推薦使用
List user1= query.list(); assertEquals(8, user1.size());
8.分頁查詢功能: hql="from User4 u order by u.id"; query=session.createQuery(hql);
query.setFirstResult(2);從零計數(shù) query.setMaxResults(10);//十分方便數(shù)據(jù)庫的移植
List userlist=query.list(); for(int i=0;i<userlist.size();i++){
User4 name=(User4)userlist.get(i); System.out.println(name.getId()); }
9.同樣支持原生SQL語句: String sql="select id ,name, age from t_user4";
Query sqlQuery=session.createSQLQuery(sql);
List result =sqlQuery.list(); for(Iterator it=result.iterator();it.hasNext();){
Object[] obj=(Object[])it.next(); Integer id=(Integer)obj[0];
String name=(String)obj[1]; Integer age=(Integer)obj[2]; }
利用得到的數(shù)據(jù): List<User4> users=new ArrayList();
User4 user4=new User4(); user4.setId(id); users.add(user4);