hibernate关联关系双向OneToOne

     其实关联关系看起来很简单,就什么一对一,一对多,多对多,但是深入发掘,你会知道其中它们之间的关系其实还是挺复杂的,所以今天先用个小例子讲讲双向一对一吧~

  • 这里我使用的是eclipse编写的一个maven+hibernate的一个例子

首先一对一,我们得在数据库中建立两个关联表,一个主键表一个外键表,然后再根据数据库去创建两个实体类,既然是双向一对一,所以说,我们可以理解为两张表之间的关系应该是互相包含的。

//主键表
package com.zking.hibernate06.entity;

public class Person {
	
	private String pid;
	private String pname;
	//外键表的实体对象(包含)
	private Card card;
	public String getPid() {
		return pid;
	}
	public void setPid(String pid) {
		this.pid = pid;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public Card getCard() {
		return card;
	}
	public void setCard(Card card) {
		this.card = card;
	}
	public Person(String pid, String pname, Card card) {
		super();
		this.pid = pid;
		this.pname = pname;
		this.card = card;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	
	

}


-------------------------------------------------------------------------

//外键表
package com.zking.hibernate06.entity;

import java.util.UUID;

public class Card {
	
	private String cid=String.valueOf(UUID.randomUUID());
	private String cno;
	private String pid;
	
	//主键表的实体对象(包含)
	private Person person;
	
	public String getPid() {
		return pid;
	}
	public void setPid(String pid) {
		this.pid = pid;
	}
	public String getCid() {
		return cid;
	}
	public void setCid(String cid) {
		this.cid = cid;
	}
	public String getCno() {
		return cno;
	}
	public void setCno(String cno) {
		this.cno = cno;
	}
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public Card() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Card(String cid, String cno, Person person) {
		super();
		this.cid = cid;
		this.cno = cno;
		this.person = person;
	}
	
	
	
	
	

}

理清楚双向一对一并建立实体类后,我们去创建一个数据库映射文件hibernate.cfg.xml文件和两个实体类映射配置文件Card.hbm.xml,Person.hbm.xml

//   hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">sasa</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mywork</property>
        <property name="hibernate.connection.username">root</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <mapping resource="com/zking/hibernate06/entity/Person.hbm.xml"/>
        <mapping resource="com/zking/hibernate06/entity/Card.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

//-------------------------------------------------------

//     Card.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 2018-9-7 19:27:19 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.zking.hibernate06.entity.Card" table="CARD">
        
        <id name="pid" type="java.lang.String">
            <column name="PID" />
         <!--设置外键 -->
            <generator class="foreign"  >
            <param name="property">person</param>
            </generator>
        </id>
        <property name="cno" type="java.lang.String">
            <column name="CNO" />
        </property>

            <property name="cid" type="java.lang.String">
            <column name="CID" />
        </property>

<!--双向一对一(外键表包含主键表对象) -->
        <one-to-one name="person" class="com.zking.hibernate06.entity.Person" ></one-to-one>
    </class>
</hibernate-mapping>

//------------------------------------------

//    Person.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 2018-9-7 19:27:19 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.zking.hibernate06.entity.Person" table="PERSON">
        <id name="pid" type="java.lang.String">
            <column name="PID" />
            <generator class="guid" />
        </id>
        <property name="pname" type="java.lang.String">
            <column name="PNAME" />
        </property>

<!--双向一对一(主键表包含外键表对象) -->
<!--级联(cascade)-->
        <one-to-one name="card" class="com.zking.hibernate06.entity.Card" cascade="all-delete-orphan"></one-to-one>
    </class>
</hibernate-mapping>

既然是双向一对一,所以我们的配置文件中也要体现包含两个词,怎么体现的呢?我们可以看到配置文件中的<one-to-one>,除了需要体现双向一对一,我们还要在外键表的配置信息中给所对应的列设置外键,但是数据库中设置成主键(理由参详下面注解)。

由于我们要对数据库表的数据进行操作,那么表与表之间又有关联关系,所以我们在操作主表的时候外表也要发生变化,这是必定的,所以我们还需要在配置中配上级联cascade。

级联:

  1. save-update:级联保存(load以后如果子对象发生了更新,也会级联更新),不会级联删除

  2. delete:级联删除

  3. all-delete-orphan:在解除父子关系的时候,自动删除不属于父对象的子对象,也支持级联删除,保存,更新(一对多)

  4. delete-orphan:删除所有和当前对象解除关联关系的对象

  5. none:默认值

一般级联的设置是在主表配置中进行设置的,虽然说hibernate会自动去筛选出主外键关系进行操作,但是有时候还是会有bug。

package com.zking.hibernate06.action;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.zking.hibernate06.entity.Card;
import com.zking.hibernate06.entity.Person;

public class OneToOneAction {
	
	private Configuration configuration;
	private SessionFactory sessionFactory;
	private Session session;
	private Transaction transaction;



	@Before
	public void before() {
		configuration = new Configuration().configure();
		sessionFactory = configuration.buildSessionFactory();
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	
	@After
	public void after() {
		session.close();
		sessionFactory.close();
	}
	
	@Test
	public void OneToOneAction() {
		//person对象
		Person p=new Person();
		p.setPname("xyj");
		//Card对象
		Card c=new Card();
		c.setCno("18473758173");
		
		/*特别注意,如果是删除的话,这里不能用c.setPerson(p),
		虽然根据可以映射找到相同的属性名进行数据操作,但是删除不会去寻找,
        新增和更新会去寻找*/
		
		//这里是删除,找到两者关联表的主键,进行删除
		c.setPid("e124359b-b29c-11e8-a86b-80fa5b48066a");
		p.setPid("e124359b-b29c-11e8-a86b-80fa5b48066a");

		//互设
		c.setPerson(p);
		p.setCard(c);
		
		

		session.save(p); //保存
		session.delete(p);//删除
		transaction.commit();

	}

}

 

注:主键表和外键表中的主外键所对应的列的列名要一致,并且外键表的所对应的列在配置中是设置成为外键,但是数据库对应的列应该设置成主键。例如:增加save()和删除delete()的话,主键表的增加要带着所对应的外键表数据的增加,它们两者又都是相互包含的关系,所以它们在hibernate框架下操作具有映射的作用,通过主键表的主键映射找到外键并附上相同的值,前提条件是,这两个键的列名也就是实体类的属性名必须一致才能赋值。删除的话,由于hibernate内置默认语法规定删除是根据表的主键来删除,所以我们在删除主键表的数据的时候也要删除外键表对应的数据,所以配置中设置成外键而在数据库应该设置成主键。

例如外键表:在配置中是设置的外键,在数据库中确实设置的主键

猜你喜欢

转载自blog.csdn.net/Mr_xiayijie/article/details/82502780