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()+" 房间的类型:"+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()+" 房间的类型:"+ 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(); }
看完了,就去实践一下吧,巩固最重要,后续会继续书写......