1.什么是對象關系映射?
解析:對象-關系映射(Object Relational Mapping,簡稱ORM,對象關系映射)是一種為了解決面向對象與關系數據庫存在的互不匹配的現象的技術。 簡單的說,ORM是通過使用描述對象和數據庫之間映射的元數據,將java程序中的對象自動持久化到關系數據庫中。本質上就是將數據從一種形式轉換到另外一種形式。
對象和關系數據是業務實體的 兩種表現形式,業務實體在內存中表現為對象,在數據庫中表現為關系數據。內存中的對象之間存在關聯和繼承關系,而在數據庫中,關系數據無法直接表達多對多 關聯和繼承關系。因此,對象-關系映射(ORM)系統一般以中間件的形式存在,主要實現程序對象到關系數據庫數據的映射。
2.多對一的關聯映射(類型表(Type)和房間表(House))
(1)准備Type和House實體類
public class Type { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class House { private Integer id; private String title; private Integer price; private String description; private String pubdate; private Integer floorage; private String contact; private Integer userid; private Integer streetid; private Type type; public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getPubdate() { return pubdate; } public void setPubdate(String pubdate) { this.pubdate = pubdate; } public Integer getFloorage() { return floorage; } public void setFloorage(Integer floorage) { this.floorage = floorage; } public String getContact() { return contact; } public void setContact(String contact) { this.contact = contact; } public Integer getUserid() { return userid; } public void setUserid(Integer userid) { this.userid = userid; } public Integer getStreetid() { return streetid; } public void setStreetid(Integer streetid) { this.streetid = streetid; } public Type getType() { return type; } public void setType(Type type) { this.type = type; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
(2)書寫HibernateUtil工具類
public class HibernateUtil { private static final ThreadLocal<Session> thLocal=new ThreadLocal<Session>(); private static Configuration cfg; private final static SessionFactory factory; static{ cfg=new Configuration().configure(); factory=cfg.buildSessionFactory(); } /** *靜態的方法 返回session */ public static Session currentSession(){ Session session = thLocal.get(); if(session==null){ session=factory.openSession(); thLocal.set(session); } return session; } /** * 靜態的方法 關閉session連接 */ public static void closeSession(){ Session session = thLocal.get(); if(session!=null){ thLocal.set(null); } session.close(); } }
(3)配置Type.hbm.xml和House.hbm.xml文件
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.lex.entity"> <class name="Type" table="TYPE"> <id name="id" > <generator class="native"></generator> </id> <property name="name"></property> </class> </hibernate-mapping>
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.lex.entity"> <class name="House" table="HOUSE"> <id name="id" > <generator class="native"></generator> </id> <property name="title"></property> <property name="contact"></property> <property name="description"></property> <property name="floorage"></property> <property name="price"></property> <property name="userid"></property> <property name="streetid"></property> <property name="pubdate"></property> <many-to-one name="type" class="cn.lex.entity.Type" column="typeid"></many-to-one> </class> </hibernate-mapping>
(4)書寫測試類
(1)第一個示例:
/** *按照指定的Type類型對象,查詢相關的House對象 */ @Test public void select(){ Session session = HibernateUtil.currentSession(); String hql="from House h where h.type.id=6"; Query query = session.createQuery(hql); List<House> list = query.list(); for (House item:list) { System.out.println("房間的標題:"+item.getTitle()+"\t房間的類型:"+item.getType().getName()); } HibernateUtil.closeSession(); }
(2)第二個示例:
/** * 輸出House集合中的所有house對象及其所關聯的type對象的信息 */ @Test public void selectAll(){ Session session = HibernateUtil.currentSession(); String hql="from House"; Query query = session.createQuery(hql); List<House> list = query.list(); for (House house:list) { System.out.println("房間的標題"+house.getTitle()+"\t房間的類型:"+ house.getType().getName()); } HibernateUtil.closeSession(); }
(3)第三個示例:
/** * 修改編號為2的房間的房間類型為2 */ @Test public void update(){ Session session = HibernateUtil.currentSession(); //先跟蹤到房間 House house = session.load(House.class, 2); //跟蹤到房間類型 Type type = session.load(Type.class, 2); house.setType(type); HibernateUtil.closeSession(); }
3.一對多雙向關聯
(1)只要在Type類中添加上一個Set<House>集合
private Set<House> house=new HashSet<House>(); public Set<House> getHouse() { return house; } public void setHouse(Set<House> house) { this.house = house; }
(2)在Type.hbm.xml中添加上<set>元素,指定哪一方維護關聯,級聯。
<set name="house" cascade="save-update" inverse="true" > <key column="typeid" ></key> <one-to-many class="cn.lex.entity.House" ></one-to-many> </set>
(3)書寫測試類
(1)第一個示例:
/** * 可以通過房間類型獲取該部分下所有房間信息 */ @Test public void select(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); String hql="from Type"; Query query = session.createQuery(hql); List<Type> list = query.list(); for (Type type :list ) { System.out.println("類型為"+type.getName()); for (House house:type.getHouse() ) { System.out.println("房間信息:"+house.getTitle()); System.out.println(house.getPrice()); System.out.println(house.getContact()); System.out.println(house.getDescription()); System.out.println(house.getFloorage()); } } tx.commit(); HibernateUtil.closeSession(); }
解析:
Hibernate: select type0_.id as id1_2_, type0_.name as name2_2_ from TYPE type0_ 類型為豪華套間 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 類型為小平房 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 房間信息:簡單干凈 3000 黃家駒 位於小鎮北面,那里環境優美,適合老人居住,配套設施齊全 50 類型為四合院 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 房間信息:讓你找到古時候的感覺 6000 喵喵喵 那里環境優美,適合老人居住,配套設施齊全 550 類型為三居室 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 房間信息:通州小鎮 6500 大頭 優質房源--地處通州開發區繁華地段,周圍配套設施齊全,肯定滿足你平時的逛街購物,房間采光好,干凈整潔,絕對不讓你白白花錢的... 200 房間信息:臨近機場高端小區 5000 川哥 優質房源--地處順義開發區繁華地段,周圍配套設施齊全,肯定滿足你平時的逛街購物,房間采光好,干凈整潔,絕對不讓你白白花錢的... 105 類型為兩居室 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 類型為一居室 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 房間信息:拆遷補貼房源 2500 坑哥 優質房源--地處昌平開發區繁華地段,周圍配套設施齊全,肯定滿足你平時的逛街購物,房間采光好,干凈整潔,絕對不讓你白白花錢的... 85 房間信息:通州優質房源 3800 劉二雄 優質房源--地處通州開發區繁華地段,周圍配套設施齊全,肯定滿足你平時的逛街購物,房間采光好,干凈整潔,絕對不讓你白白花錢的... 120 房間信息:開發區優質房源 4800 刀哥 優質房源--地處通州繁華地段,周圍配套設施齊全,肯定滿足你平時的逛街購物,房間采光好,干凈整潔,絕對不讓你白白花錢的... 86 類型為合租房 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 房間信息:朴素的小區 1500 飄哥 優質房源--地處大興開發區繁華地段,周圍配套設施齊全,肯定滿足你平時的逛街購物,房間采光好,干凈整潔,絕對不讓你白白花錢的... 123 類型為別墅房 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 房間信息:海淀中關村便宜房源 2700 GAY達 優質房源--地處海淀開發區繁華地段,周圍配套設施齊全,肯定滿足你平時的逛街購物,房間采光好,干凈整潔,絕對不讓你白白花錢的... 145 房間信息:高端住宅 5050 鳳飛飛 位於小鎮南面,那里環境優美,配套設施齊全,絕對是你居家的首選 400 類型為LOFT公寓 Hibernate: select house0_.typeid as typeid10_0_0_, house0_.id as id1_0_0_, house0_.id as id1_0_1_, house0_.title as title2_0_1_, house0_.contact as contact3_0_1_, house0_.description as description4_0_1_, house0_.floorage as floorage5_0_1_, house0_.price as price6_0_1_, house0_.userid as userid7_0_1_, house0_.streetid as streetid8_0_1_, house0_.pubdate as pubdate9_0_1_, house0_.typeid as typeid10_0_1_ from HOUSE house0_ where house0_.typeid=? 房間信息:高端住宅 4000 鳳飛飛 那里環境優美,交通便利,周圍配套設施齊全,絕對是你居家的首選 260
(2)第二個示例:
/** * 可以通過某個房間獲取該房間所在的類型 */ @Test public void select1(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); House house = session.load(House.class, 1); System.out.println(house.getType().getName()); tx.commit(); HibernateUtil.closeSession(); }
(3)第三個示例:
/** * 保存一個房間類型 使用級聯保存房間信息 cascade */ @Test public void add(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //先創建類型 Type type=new Type(); type.setName("小平房"); //創建房間 House house=new House(); house.setTitle("簡單干凈"); house.setDescription("位於小鎮北面,那里環境優美,適合老人居住,配套設施齊全"); house.setPrice(3000); house.setFloorage(50); house.setContact("黃家駒"); house.setPubdate("2017-1-16"); house.setUserid(2); house.setStreetid(2); house.setType(type); //關聯類型和房間 type.getHouse().add(house); //保存 session.save(type); tx.commit(); HibernateUtil.closeSession(); }
(4)第四個示例:
/** * 保存一個房間類型 使用級聯保存房間信息 inverse 位false */ @Test public void add1(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //先創建類型 Type type=new Type(); type.setName("四合院"); //創建房間 House house=new House(); house.setTitle("讓你找到古時候的感覺"); house.setDescription("位於小鎮南面,那里環境優美,適合老人居住,配套設施齊全"); house.setPrice(6000); house.setFloorage(550); house.setContact("喵喵喵"); house.setPubdate("2017-1-16"); house.setUserid(1); house.setStreetid(2); house.setType(type); //關聯類型和房間 type.getHouse().add(house); //保存 session.save(type); tx.commit(); HibernateUtil.closeSession(); }
(5)第五個示例:
/** * order by 排序 */ @Test public void select2(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); String hql="from Type"; Query query = session.createQuery(hql); List<Type> list = query.list(); for (Type type :list ) { for (House house :type.getHouse()) { System.out.println(house.getId()+house.getTitle()); } } tx.commit(); HibernateUtil.closeSession(); }
3.多對多單向關聯(House類和Users類)
(1)House類中添加Set<Users>集合
Users實體類:
public class Users { private Integer id; private String name; private String password; private String telephone; private String username; private String isadmin; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getIsadmin() { return isadmin; } public void setIsadmin(String isadmin) { this.isadmin = isadmin; } }
private Set<Users> users=new HashSet<Users>(); public Set<Users> getUsers() { return users; } public void setUsers(Set<Users> users) { this.users = users; }
(2)在House.hbm.xml中添加<set>元素
<set name="users" table="PROHOUSE" inverse="true"> <key column="RHOUSEID"></key> <many-to-many class="cn.lex.entity.Users" column="PROID"></many-to-many> </set>
(3)測試:
/** * 多對多單向關聯 */ @Test public void add(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //創建用戶 Users users=new Users(); users.setName("奈克"); users.setPassword("000120"); users.setTelephone("2131313213"); users.setUsername("DDS"); users.setIsadmin("0"); //創建房子 House house=new House(); house.setTitle("高端住宅"); house.setDescription("位於小鎮南面,那里環境優美,配套設施齊全,絕對是你居家的首選"); house.setPrice(5050); house.setFloorage(400); house.setContact("鳳飛飛"); house.setPubdate("2017-1-14"); house.setUserid(1); house.setStreetid(3); House house2=new House(); house2.setTitle("高端住宅"); house2.setDescription("那里環境優美,交通便利,周圍配套設施齊全,絕對是你居家的首選"); house2.setPrice(4000); house2.setFloorage(260); house2.setContact("鳳飛飛"); house2.setPubdate("2017-1-06"); house2.setUserid(5); house2.setStreetid(1); //關聯關系 users.getHouse().add(house); users.getHouse().add(house2); session.save(users); tx.commit(); HibernateUtil.closeSession(); }
4.多對多雙向關聯
(1)在Users類中添加Set<House>集合
private Set<House> house=new HashSet<House>(); public Set<House> getHouse() { return house; } public void setHouse(Set<House> house) { this.house = house; }
(2)在Users.hbm.xml中添加<set>元素
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.lex.entity"> <class name="Users" table="USERS"> <id name="id" > <generator class="native"></generator> </id> <property name="name"></property> <property name="username"></property> <property name="password"></property> <property name="isadmin"></property> <property name="telephone"></property> <set name="house" cascade="save-update" table="PROHOUSE"> <key column="PROID"></key> <many-to-many class="cn.lex.entity.House" column="RHOUSEID"></many-to-many> </set> </class> </hibernate-mapping>
(3)測試類:
/** * 多對多雙向關聯 */ @Test public void add1(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //創建用戶 Users users=new Users(); users.setName("娜娜"); users.setPassword("123456"); users.setTelephone("1111111111"); users.setUsername("嚕啦啦"); users.setIsadmin("0"); //創建房子 House house=new House(); house.setTitle("普通住宅"); house.setDescription("位於小鎮南面,那里環境優美,配套設施齊全,絕對是你居家的首選"); house.setPrice(1000); house.setFloorage(400); house.setContact("飛飛"); house.setPubdate("2017-01-01"); house.setUserid(2); house.setStreetid(6); House house2=new House(); house2.setTitle("高端住宅"); house2.setDescription("那里環境優美,交通便利,周圍配套設施齊全,絕對是你居家的首選"); house2.setPrice(4000); house2.setFloorage(260); house2.setContact("鳳飛飛"); house2.setPubdate("2017-1-06"); house2.setUserid(5); house2.setStreetid(1); //關聯關系 users.getHouse().add(house); house.getUsers().add(users); session.save(users); tx.commit(); HibernateUtil.closeSession(); }
看完了,就去實踐一下吧,鞏固最重要,后續會繼續書寫......