hibernate的一对一主键双向映射关系和外键双向映射关系(一)

主键关联的重点是关联的两个表共享一个主键值。本例中采用,一个单位在网上的一个系统中注册会员。

1,会员数据保存在会员表company中,每个会员的登录账号保存在表login中;

2,一个会员只有一个登录账号,一个登录账号只属于一个会员,两表是一对一的对应关系;

company表如下:


生成company表的sql语句如下:

CREATE TABLE `company` (
`ID`  int(4) NOT NULL AUTO_INCREMENT ,
`COMPANYNAME`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`LINKMAN`  char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`TELEPHONE`  char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`EMAIL`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`ID`)
)

login表如下:


生成login表的sql语句如下:

<pre name="code" class="sql">CREATE TABLE `login` (
`ID`  int(4) NOT NULL ,
`LOGINNAME`  char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`LOGINPWD`  char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`ID`)
)

 

外键关联的重点是:两个表各自有不同的主键,但是其中一个表有一个外键引用另一个表的主键。即非主键是别人的主键就是该表的外键。

这个例子中:

1,客户(Client)和客户地址(Address)是外键关联的一对一关系,分别对应client表换个address表。

2,Client类在映射文件中的client_address为外键引用Address类的对应表中的主键,咋一看书多对一关系,但是在Client类对应的映射文件设置多对一对应的属性client_address时,设置了unique的值为true,即这个外键是唯一的,即一对一关系。

client表如下:

生成client表的sql语言:

CREATE TABLE `client` (
`ID`  int(4) NOT NULL AUTO_INCREMENT ,
`CLIENTNAME`  char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`PHONE`  char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`EMAIL`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`CLIENTADDRESSID`  int(4) NULL DEFAULT NULL ,
PRIMARY KEY (`ID`),
FOREIGN KEY (`CLIENTADDRESSID`) REFERENCES `address` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `CLIENTADDRESSID` (`CLIENTADDRESSID`) USING BTREE 
)
注意:这里的CLIENTADDRESSID是外键,client表也要设置外键



address表如下:



CREATE TABLE `address` (
`ID`  int(4) NOT NULL AUTO_INCREMENT ,
`PROVINCE`  varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`CITY`  varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`STREET`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`ZIPCODE`  char(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`ID`)
)

hibernate.cfg.xml配置文件:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

<session-factory>
	<property name="dialect">
		org.hibernate.dialect.MySQLInnoDBDialect
	</property>
	<property name="connection.url">jdbc:mysql://localhost:3306/onetoone</property>
	<property name="connection.username">root</property>
	<property name="connection.password">123456</property>
	<property name="connection.driver_class">
		com.mysql.jdbc.Driver
	</property>
	
	<!-- 显示sql语句 -->
    <property name="hibernate.show_sql">true </property>  
    <property name="format_sql">true</property><!-- 让输出的sql语句格式化 -->
	<mapping resource="com/hust/javabeans/Address.hbm.xml" />
	<mapping resource="com/hust/javabeans/Client.hbm.xml"  />
	<mapping resource="com/hust/javabeans/Company.hbm.xml" />
	<mapping resource="com/hust/javabeans/Login.hbm.xml"    />

</session-factory>

</hibernate-configuration>

一对一主键双向关联:

Company.java

package com.hust.javabeans;
import java.io.Serializable;
public class Company implements Serializable {
      /**
	 * 
	 */
      private Integer id;
      private String companyname;
      private String linkman;
      private String telephone;
      private String email;
     
      private Login login;       //关联另外一个类,即保证Company对象中有Login对象的信息,体现一对一关联
	
      public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getCompanyname() {
		return companyname;
	}
	public void setCompanyname(String companyname) {
		this.companyname = companyname;
	}
	public String getLinkman() {
		return linkman;
	}
	public void setLinkman(String linkman) {
		this.linkman = linkman;
	}
	public String getTelephone() {
		return telephone;
	}
	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Login getLogin() {
		return login;
	}
	public void setLogin(Login login) {
		this.login = login;
	}
    
}
Login.java

package com.hust.javabeans;
import java.io.Serializable;
public class Login implements Serializable {
      /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
      private Integer id;
      private String loginname;
      private String loginpwd;
      
      private Company company;   //关联另外一个类,即保证Login对象中有Company对象的信息,体现一对一关联
	
      public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getLoginname() {
		return loginname;
	}
	public void setLoginname(String loginname) {
		this.loginname = loginname;
	}
	public String getLoginpwd() {
		return loginpwd;
	}
	public void setLoginpwd(String loginpwd) {
		this.loginpwd = loginpwd;
	}
	public Company getCompany() {
		return company;
	}
	public void setCompany(Company company) {
		this.company = company;
	}
      
}
Company.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping >
   <class name="com.hust.javabeans.Company" table="company">
     <id column="ID" name="id" type="integer">
        <generator class="identity"></generator>
     </id>
     <property name="companyname" column="COMPANYNAME" type="string"></property>
     <property name="linkman"     column="LINKMAN" type="string"></property>
     <property name="telephone"   column="TELEPHONE" type="string"></property>
     <property name="email"       column="EMAIL" type="string"></property>
     
     <!-- 映射Company与Login的一对一主键关联 -->
     <one-to-one name="login" class="com.hust.javabeans.Login" cascade="all" lazy="false" fetch="join" outer-join="true"></one-to-one>
 
   </class>
</hibernate-mapping>
Login.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
   <class name="com.hust.javabeans.Login" table="login">
        <!-- 使用外键生成机制(foreign),引用表company的主键作为login表的主键值 ,定义了外键的生成策略,这样可以在级联插入时保持company的主键和login的外键(也是主键)相同。-->
       <id name="id" column="ID" type="integer">
          <generator class="foreign">
            <param name="property">company</param>
          </generator>
       </id>
       
       <property name="loginname" column="LOGINNAME" type="string"></property>
       <property name="loginpwd" column="LOGINPWD" type="string"></property>
       
       <!-- 映射Company与Login的一对一主键关联 --> 
       <one-to-one name="company" class="com.hust.javabeans.Company" constrained="true"></one-to-one><!-- constrained="true"表示Login引用了company的主键作为外键 -->
  
   </class>
</hibernate-mapping>

一对一外键双向关联:

Client.java

package com.hust.javabeans;

import java.io.Serializable;

public class Client implements Serializable {
       private Integer id;
       private String clientname;
       private String phone;
       private String email;
       
       private Address client_address;  //关联另一个类
       
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getClientname() {
		return clientname;
	}
	public void setClientname(String clientname) {
		this.clientname = clientname;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Address getClient_address() {
		return client_address;
	}
	public void setClient_address(Address client_address) {
		this.client_address = client_address;
	}
	  
       
}
Address.java

package com.hust.javabeans;
import java.io.Serializable;
public class Address implements Serializable {
   private Integer id;
   private String province;
   private String city;
   private String street;
   private String zipcode;
   
   private Client address_client;//关联另外一个类

   public Integer getId() {
	   return id;
   }

   public void setId(Integer id) {
	   this.id = id;
   }

   public String getProvince() {
	   return province;
   }

   public void setProvince(String province) {
	   this.province = province;
   }

   public String getCity() {
	   return city;
   }

   public void setCity(String city) {
	   this.city = city;
   }

   public String getStreet() {
	   return street;
   }

   public void setStreet(String street) {
	   this.street = street;
   }

   public String getZipcode() {
	   return zipcode;
   }

   public void setZipcode(String zipcode) {
	   this.zipcode = zipcode;
   }

public Client getAddress_client() {
	return address_client;
}

public void setAddress_client(Client address_client) {
	this.address_client = address_client;
}
    
}
Client.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
   <class name="com.hust.javabeans.Client" table="client">
     <id name="id" column="ID"  type="integer">
        <generator class="identity"></generator>
     </id>
     
     <property name="clientname" column="CLIENTNAME" type="string"></property>
     <property name="phone" column="PHONE" type="string"></property>
     <property name="email" column="EMAIL" type="string"></property>
     
     <!-- 映射Client和Address的一对一外键关联,唯一多对一,实际上时一对一关系,这里的name是Client的属性,column是client表的外键-->
     <many-to-one name="client_address" class="com.hust.javabeans.Address" column="CLIENTADDRESSID" cascade="all" lazy="false" unique="true"></many-to-one>
   </class>
</hibernate-mapping>

<many-to-one unique="true"> 标签在这里表示一对一,many-to-one应该写在有外键的那个表对应的映射文件中

Address.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                                   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
 <class name="com.hust.javabeans.Address" table="address">
  <id column="ID" name="id" type="integer">
   <generator class="identity"/>
  </id>
  <property name="province" column="PROVINCE"  type="string"/>
  <property name="city"     column="CITY"    type="string"/>
  <property name="street"   column="STREET"  type="string"/>
  <property name="zipcode"  column="ZIPCODE" type="string"/>
   
   <!-- 映射Client和Address的一对一外键关联,name是Address的属性,property-ref是Client中的属性<span style="font-family:Arial, Helvetica, sans-serif;">client_address--></span>
  <one-to-one name="address_client" class="com.hust.javabeans.Client"  property-ref="client_address"/> 
 </class>
</hibernate-mapping>


访问数据库文件OneOneDao.java

package com.hust.dao;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hust.javabeans.Client;
import com.hust.javabeans.Company;
import SessionFactory.HibernateSessionFactory;

public class OneOneDao {
    //添加会员 的方法,只操作主控方
	public  void addCompany(Company company){
		Session session=HibernateSessionFactory.getSession();
		Transaction ts=null;
		try{
			ts=session.beginTransaction();
			
			System.out.println("oneonedao的addCompany方法执行,执行的sql:");
			session.save(company);
			System.out.println("oneonedao的addCompany方法完成");
			
			ts.commit();			
		}catch(Exception ex){
			ts.rollback();
			System.out.println("[系统错误]oneonedao的addCompany方法中出错");
			ex.printStackTrace();			
		}finally{
			HibernateSessionFactory.closeSession();
		}		
	}
	
	  //获取会员信息
		public Company loadCompany(Integer id){
			Session session=HibernateSessionFactory.getSession();
			Transaction ts=null;
			Company company=null;
			try{
				ts=session.beginTransaction();
				
				System.out.println("oneonedao的loadCompany方法执行,执行的sql:");
				company=(Company)session.get(Company.class, id);
				System.out.println("oneonedao的loadCompany方法完成");
				
				ts.commit();			
				
			}catch(Exception ex){
				ts.rollback();
				System.out.println("[系统错误]早oneonedao的loadCompany方法中出错");
				ex.printStackTrace();			
			}finally{
				HibernateSessionFactory.closeSession();
			}
			return company;
		}
	 //添加客户信息,<span style="font-family: Arial, Helvetica, sans-serif;">只操作主控方</span>

		public void addClient(Client client){
			Session session=HibernateSessionFactory.getSession();
			Transaction ts=null;
			try{
				ts=session.beginTransaction();
				
				System.out.println("oneonedao的addclient方法执行,执行的sql:");
				session.save(client);		
				System.out.println("oneonedao的addclient方法完成");
				
				ts.commit();			
			}catch(Exception ex){
				ts.rollback();
				System.out.println("[系统错误]oneonedao的addClient方法中出错");
				ex.printStackTrace();			
			}finally{
				HibernateSessionFactory.closeSession();
			}	
		}

		  //获取客户信息
			public Client loadClient(Integer id){
				Session session=HibernateSessionFactory.getSession();
				Transaction ts=null;
				Client client=null;
				try{
					ts=session.beginTransaction();
					
					System.out.println("oneonedao的loadclient方法执行,执行的sql:");
					client=(Client)session.get(Client.class, id);
					System.out.println("oneonedao的loadclient方法完成");
					
					ts.commit();			
					
				}catch(Exception ex){
					ts.rollback();
					System.out.println("[系统错误]oneonedao的loadclient方法中出错");
					ex.printStackTrace();			
				}finally{
					HibernateSessionFactory.closeSession();
				}
				return client;
			}
}
TestBean.java

package com.hust.test;

import com.hust.dao.OneOneDao;
import com.hust.javabeans.Address;
import com.hust.javabeans.Client;
import com.hust.javabeans.Company;
import com.hust.javabeans.Login;

public class TestBean {
         OneOneDao oneonedao=new OneOneDao();
         //获取会员信息
         public void addCompany(){
        	 Company company=new Company();
        	 Login login=new Login();
        	 
        	 login.setLoginname("tuke");
        	 login.setLoginpwd("123456");
        	 
        	 company.setCompanyname("呵呵哒的微笑");
        	 company.setLinkman("张珊");
        	 company.setTelephone("010-12345678");
        	 company.setEmail("beijing@163.com");
        	 
        	 //PO对象之间互相设置关联关系
        	 login.setCompany(company);
        	 company.setLogin(login);
        	 System.out.println("testbean的addcompany方法执行开始");
        	 //添加会员信息,保存到数据库,company保存到数据库,同时login也保存到数据库,只操作主控方
        	 oneonedao.addCompany(company);
        	 System.out.println("testbean的addcompany方法执行完成");
         }
         //获取会员信息
         public Company loadCompany(Integer id){
        	 //从数据库获得company的同时也获得了login表的记录
        	 System.out.println("testbean的loadcompany方法执行开始");
        	 return oneonedao.loadCompany(id);
         }
         
        //添加客户信息
         public void addClient(){
        	 Client client=new Client();
        	 Address address=new Address();
        	 
        	 address.setProvince("湖北省");
        	 address.setCity("武汉市");
        	 address.setStreet("临江大道");
        	 address.setZipcode("100083");
        	 
        	 client.setClientname("李想");
        	 client.setPhone("027-76866876");
        	 client.setEmail("lixiang@126.com");
        	
        	//PO对象之间互相设置关联关系
        	 address.setAddress_client(client);
        	 client.setClient_address(address);
        	 
        	 System.out.println("testbean的addclient方法执行开始");
        	 //添加客户信息,保存到数据库,client保存到数据库,同时address也保存到数据库,只操作主控方
        	 oneonedao.addClient(client);
        	 System.out.println("testbean的addclient方法执行完成");
         }
         //获得客户信息
         public Client loadClient(Integer id){
        	 System.out.println("testbean的loadclient方法执行开始");
        	 return oneonedao.loadClient(id);
         }
         
}
结果显示为:






控制台打印的sql是:

testbean的addcompany方法执行开始
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
oneonedao的addCompany方法执行,执行的sql:
Hibernate: 
    insert 
    into
        company
        (COMPANYNAME, LINKMAN, TELEPHONE, EMAIL) 
    values
        (?, ?, ?, ?)
oneonedao的addCompany方法完成
Hibernate: 
    insert 
    into
        login
        (LOGINNAME, LOGINPWD, ID) 
    values
        (?, ?, ?)
testbean的addcompany方法执行完成       //主键关联时,两个insert语句不是连续完成的
testbean的addclient方法执行开始
oneonedao的addclient方法执行,执行的sql:
Hibernate: 
    insert 
    into
        address
        (PROVINCE, CITY, STREET, ZIPCODE) 
    values
        (?, ?, ?, ?)
Hibernate: 
    insert 
    into
        client
        (CLIENTNAME, PHONE, EMAIL, CLIENTADDRESSID) 
    values
        (?, ?, ?, ?)
oneonedao的addclient方法完成
testbean的addclient方法执行完成       //外键关联时,连续执行两个insert语句
testbean的loadcompany方法执行开始
oneonedao的loadCompany方法执行,执行的sql:
Hibernate: 
    select
        company0_.ID as ID2_1_,
        company0_.COMPANYNAME as COMPANYN2_2_1_,
        company0_.LINKMAN as LINKMAN2_1_,
        company0_.TELEPHONE as TELEPHONE2_1_,
        company0_.EMAIL as EMAIL2_1_,
        login1_.ID as ID3_0_,
        login1_.LOGINNAME as LOGINNAME3_0_,
        login1_.LOGINPWD as LOGINPWD3_0_ 
    from
        company company0_ 
    left outer join
        login login1_ 
            on company0_.ID=login1_.ID 
    where
        company0_.ID=?
oneonedao的loadCompany方法完成
testbean的loadclient方法执行开始
oneonedao的loadclient方法执行,执行的sql:
Hibernate: 
    select
        client0_.ID as ID1_0_,
        client0_.CLIENTNAME as CLIENTNAME1_0_,
        client0_.PHONE as PHONE1_0_,
        client0_.EMAIL as EMAIL1_0_,
        client0_.CLIENTADDRESSID as CLIENTAD5_1_0_ 
    from
        client client0_ 
    where
        client0_.ID=?
Hibernate: 
    select
        address0_.ID as ID0_1_,
        address0_.PROVINCE as PROVINCE0_1_,
        address0_.CITY as CITY0_1_,
        address0_.STREET as STREET0_1_,
        address0_.ZIPCODE as ZIPCODE0_1_,
        client1_.ID as ID1_0_,
        client1_.CLIENTNAME as CLIENTNAME1_0_,
        client1_.PHONE as PHONE1_0_,
        client1_.EMAIL as EMAIL1_0_,
        client1_.CLIENTADDRESSID as CLIENTAD5_1_0_ 
    from
        address address0_ 
    left outer join
        client client1_ 
            on address0_.ID=client1_.CLIENTADDRESSID 
    where
        address0_.ID=?
Hibernate: 
    select
        client0_.ID as ID1_0_,
        client0_.CLIENTNAME as CLIENTNAME1_0_,
        client0_.PHONE as PHONE1_0_,
        client0_.EMAIL as EMAIL1_0_,
        client0_.CLIENTADDRESSID as CLIENTAD5_1_0_ 
    from
        client client0_ 
    where
        client0_.CLIENTADDRESSID=?
oneonedao的loadclient方法完成



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值