hibernate映射详解,这里是一对一映射的单讲:
本例采用phone和simcard实例:
phone和phone.hbm.xml:
Phone类:
package hibernate_onToOne;
public class Phone {
private int id;
private String name;
//一对一映射时不要实例化,因为数据库中没有对应的表,hibernate不认识该对象
//无法生成代理
private SimCard simCard;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SimCard getSimCard() {
return simCard;
}
public void setSimCard(SimCard simCard) {
this.simCard = simCard;
}
@Override
public String toString() {
return "Phone: [id=" + id + ", name=" + name + "]";
}
}
phone.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-4-3 16:12:29 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="hibernate_onToOne">
<class name="Phone" table="phone">
<id name="id" type="int">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="string">
<column name="name" />
</property>
<!-- 一对一形式有两种实现方法:一种是基于外键的实现,然后在外键上加上unique约束,
这种方式从有外键方可以解除关联,常用
一种是基于主键引用的方式,不可以解除关联
-->
<!-- <one-to-one name="simCard" class="SimCard" property-ref="phone">
采用基于外键的一对一映射方式,本方无外键方。
property-ref属性:
写的是对方映射中外键列对应的属性名
</one-to-one> -->
<!-- 基于主键的一对一方式:
采用基于主键的一对一映射方式,本方无外键方。
只需设置关联对象即可-->
<one-to-one name="simCard" class="SimCard"></one-to-one>
</class>
</hibernate-mapping>
SimCard和Simcard.hbm.xml:
SimCard类:
package hibernate_onToOne;
public class SimCard {
private int id;
private String number;
//一对一映射时不要实例化,因为数据库中没有对应的表,hibernate不认识该对象
//无法生成代理
private Phone phone;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Phone getPhone() {
return phone;
}
public void setPhone(Phone phone) {
this.phone = phone;
}
@Override
public String toString() {
return "simCard [id=" + id + ", number=" + number + "]";
}
}
SimCard.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-4-3 16:12:29 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="hibernate_onToOne">
<class name="SimCard" table="simcard">
<id name="id" type="int">
<column name="ID" />
<!-- 当使用基于主键的一对一映射时,
有外键方的主键生成策略一定要是foreign。
参数property:
生成主键值时所根据的对象。
-->
<generator class="foreign" >
<param name="property">phone</param>
</generator>
</id>
<property name="number" type="string">
<column name="number" />
</property>
<!-- 一对一形式有两种实现方法:一种是基于外键的实现,然后在外键上加上unique约束,
这种方式从有外键方可以解除关联,常用:
一种是基于主键引用的方式,不可以解除关联 -->
<!-- <many-to-one name="phone" class="Phone" column="phoneID" unique="true">
表达的是本类与Phone的一对一。
采用基于外键的一对一映射方式,本方有外键方,注意添加唯一约束
</many-to-one> -->
<!-- 基于主键的一对一方式,双方都是one-to-one标签,
constrained只能在one-to-one的映射中使用,(一般在主表的映射中,有外键的那个表)。
如果constrained=true, 则表明存在外键与关联表对应,并且关联表中肯定存在对应的键与其对应,
另外该选项最关键的是影响save和delete的先后顺序。例如增加的时候,
如果constainted=true,则会先增加关联表,然后增加本表。 删除的时候反之。
: -->
<one-to-one name="phone" class="Phone" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
测试类:
package hibernate_onToOne;
import hibernate_manyeToMany.Student;
import hibernate_manyeToMany.Teacher;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
/**
* @author 梁磊
*
*/
public class App {
static SessionFactory sessionFactory;
static{
//初始化数据
sessionFactory=new Configuration().configure()
.addClass(Phone.class).addClass(SimCard.class)
.buildSessionFactory();
}
@Test
public void testSave() {
//新建对像
Phone phone=new Phone();
phone.setName("小米");
SimCard card=new SimCard();
card.setNumber("12345566");
//关联起来
phone.setSimCard(card);
card.setPhone(phone);
//保存
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(phone);
session.save(card);
session.getTransaction().commit();
}
@Test
public void testGet() {
//测试获取一方
Session session=sessionFactory.openSession();
session.beginTransaction();
//获取PHone得到simcard
Phone phone=(Phone) session.get(Phone.class, 1);
System.out.println(phone);
System.out.println(phone.getSimCard());
//获取simcard得到phone
/*SimCard simCard=(SimCard) session.get(SimCard.class, 1);
System.out.println(simCard);
System.out.println(simCard.getPhone());*/
session.getTransaction().commit();
}
/**
* 测试解除关联关系
*/
@Test
public void testRemove() {
Session session=sessionFactory.openSession();
session.beginTransaction();
//从phone方解除关联
//不会发生update语句,因为phone是外键方,不维护外键,所以解除关系只能从有外键方解除
Phone phone=(Phone) session.get(Phone.class, 1);
phone.setSimCard(null);
//解除关系只能从有外键方解除关系,被引用方无法解除关联
/* SimCard simCard=(SimCard) session.get(SimCard.class, 1);
simCard.setPhone(null);*/
//当使用基于主键的关联方式时,由于主键无法为空,所以不会执行sql语句,当然也无法解除关联
session.getTransaction().commit();
}
/**
* 测试删除一方
*/
@Test
public void testDelete() {
Session session=sessionFactory.openSession();
session.beginTransaction();
//数据的删除,如果删除外键方会报错,凡是学过数据的同学都知道这点,所以当我们要删除外键方对象时,要先把引用置空才能删除
//直接删除实惠报错的,所以我们只能这样删除
/* Phone phone=(Phone) session.get(Phone.class, 1);
//session.delete(phone);
//先把引用置空,这样就可以保证在删除phone的同时不会删除simcard
phone.getSimCard().setPhone(null);
session.delete(phone);*/
//删除有外键方,直接会删除,delete from simcard where ID=?
/*SimCard simCard=(SimCard) session.get(SimCard.class, 1);
session.delete(simCard);*/
//采用基于逐渐的一对一映射,所以可以从外键方删除
SimCard simCard=(SimCard) session.get(SimCard.class, 1);
session.delete(simCard);
//当删除phone,由于simCard的主键是基于phone的主键生成的,所以删除phone的记录时由于有外键引用,就会报
/* Phone phone=(Phone) session.get(Phone.class, 1);
session.delete(phone);*/
session.getTransaction().commit();
}
}
配置:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 指定方言,指定mysql ,建议配置成上面,不然hibernate在执行创建表的时候会报错,目前没有找到原因-->
<property name="hbm2ddl.auto">update</property><!-- -这个参数指定,hibernate可以更新数据,当为create时,hibernate每次执行插入操作都会先删除表,然后在创建表插入数据 -->
<property name="show_sql">true</property><!-- -这个参数,表示,hibernate会把自动生成的参数,显示在控制台给我们看,一般用于开发阶段 -->
<!-- 这个属性是设置事务隔离级别的
1:表示读未提交
2:表示读已提交
4:可重复读
8:串行化(不可并发) -->
<property name="hibernate.connection.isolation">2</property>
<!-- <mapping resource="com/leige/domain/User.hbm.xml"/> --><!-- -指定映射文件,告诉hibernate,对象与表的映射关系 -->
</session-factory>
</hibernate-configuration>