什么时候采用一对一关系映射呢?
比如我们有时在网上注册的时候,用户名,密码,邮箱必填,然后提供了一个复选框,可以选填用户的详细资料.那么如果在数据库中, 我们通常会建两张表,如下:
主表 从表
但是在Hibernate中会怎么实现这个呢,大家过细观察一下,会不会觉得这个外键有点多余,如果我们让从表的ID和主表的ID一样,即让从表的ID即是主键又是外键,会不会更好呢,Hibernate中就是这样实现一对一的关系的.
那么下面请看具体代码:
我们将利用自动创建SQL的特点来建表,我们就不需要建表了,只需要建立类,关联类之间的关系就可以了.
UserBase:
public class UserBase { private String id; private String userAccount; private String userPwd; private String userEmail; private UserData userData;
public UserBase() { super(); }
public UserBase(String userAccount, String userPwd, String userEmail) { super(); this.userAccount = userAccount; this.userPwd = userPwd; this.userEmail = userEmail; }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getUserAccount() { return userAccount; }
public void setUserAccount(String userAccount) { this.userAccount = userAccount; }
public String getUserPwd() { return userPwd; }
public void setUserPwd(String userPwd) { this.userPwd = userPwd; }
public String getUserEmail() { return userEmail; }
public void setUserEmail(String userEmail) { this.userEmail = userEmail; }
public UserData getUserData() { return userData; }
public void setUserData(UserData userData) { this.userData = userData; } } |
UserData:
import java.util.Date;
public class UserData { private String id; private String userName; private Date birthday; private String mobile; private UserBase userBase;
public UserData() { super(); }
public UserData(String userName, Date birthday, String mobile) { super(); this.userName = userName; this.birthday = birthday; this.mobile = mobile; }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; }
public Date getBirthday() { return birthday; }
public void setBirthday(Date birthday) { this.birthday = birthday; }
public String getMobile() { return mobile; }
public void setMobile(String mobile) { this.mobile = mobile; }
public UserBase getUserBase() { return userBase; }
public void setUserBase(UserBase userBase) { this.userBase = userBase; } } |
UserBase.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="chapter3.model.UserBase" table="user_base"> <id name="id" type="java.lang.String" column="id" length="32"> <generator class="uuid.hex" /> </id> <property name="userAccount" type="java.lang.String" column="userAccount" length="20" /> <property name="userPwd" type="java.lang.String" column="userPwd" length="20" /> <property name="userEmail" type="java.lang.String" column="userEmail" length="50" /> <one-to-one name="userData" class="chapter3.model.UserData" /> </class> </hibernate-mapping> |
UserData.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="chapter3.model.UserData" table="user_data"> <id name="id" type="java.lang.String" column="id" length="32"> <generator class="foreign"> <param name="property">userBase</param> </generator> </id> <property name="userName" type="java.lang.String" column="userName" length="50" /> <property name="birthday" type="java.util.Date" column="birthday" length="10" /> <property name="mobile" type="java.lang.String" column="mobile" length="11" /> <one-to-one name="userBase" class="chapter3.model.UserBase" /> </class> </hibernate-mapping> |
UserBaseDao:
public class UserBaseDao { public void create(UserBase userBase) throws Exception { Session session = null; try { session = HibernateUtil.getSession(); session.beginTransaction(); session.save(userBase); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw e; } }
public UserBase findById(Serializable id) throws Exception { Session session = null; UserBase userBase = null; try { session = HibernateUtil.getSession(); session.beginTransaction(); userBase = (UserBase) session.get(UserBase.class, id); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw e; } return userBase; } } |
UserDataDao:
public class UserDataDao { public void create(UserData userData) throws Exception { Session session = null; try { session = HibernateUtil.getSession(); session.beginTransaction(); session.save(userData); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw e; } }
public UserData findById(Serializable id) throws Exception { Session session = null; UserData userData = null; try { session = HibernateUtil.getSession(); session.beginTransaction(); userData = (UserData) session.get(UserData.class, id); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw e; } return userData; } } |
Test:
public class Test { public static void main(String[] args) throws Exception { UserBaseDao userBaseDao = new UserBaseDao(); UserDataDao userDataDao = new UserDataDao();
UserBase userBase = new UserBase("zhanghaidang", "791126", "wdpc@163.com"); userBaseDao.create(userBase);
UserData userData = new UserData("张海当", new Date(), "13986007262"); userData.setUserBase(userBase); userDataDao.create(userData); } } |
总结:
主键关联一对一映射不需要额外的字段,对象之间必须共享相同的主键;
一对一映射默认采用级联操作,存储一个对象的时候,另一个对象也同时被储存;
配置子表的主键时,注意主键的生成策略:
<id name="id" type="java.lang.String" column="id" length="32">
<generator class="foreign">
<param name="property">userBase</param>
</generator>
</id>
采用的是foreign外键策略,意指该表的主键来自另一张表, 并且需要告诉策略对应的类,可以查看源码包下的ForeignGenerator类的源代码,重点看下面的代码,该类会获取一个参数 params.getProperty("property"); 那么这时我们需要将property参数的值传给它, 传参的代码为上面的形式.
public void configure(Type type, Properties params, Dialect d) throws MappingException { propertyName = params.getProperty("property"); entityName = params.getProperty(ENTITY_NAME); if (propertyName==null) throw new MappingException( "param named /"property/" is required for foreign id generation strategy" ); } |
运用的时候需要注意,一定要先创建主表的对应类,因为只有创建了主表的对应类,子表才能够取得ID主键,从而为自己设置主键的值.