您的位置:首页 > 其它

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

2015-11-12 23:07 447 查看
主键关联的重点是关联的两个表共享一个主键值。本例中采用,一个单位在网上的一个系统中注册会员。

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方法完成
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息