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 + "]"; } }
<?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类:
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>