Hibernate高级实体关联映射之单值的实体关联(用联结表映射)

 

 

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hibernateTest</groupId> <artifactId>hibernateTest</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>hibernateTest</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.3.1.GA</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-nop</artifactId> <version>1.5.2</version> </dependency> <dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.4.GA</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc14</artifactId> <version>10.2.0.3.0</version> <scope>runtime</scope> </dependency> </dependencies> <build> <finalName>hibernateTest</finalName> <resources> <resource> <directory>src/main/resources</directory> </resource> <resource> <directory>src/main/java</directory> <excludes> <exclude>**/*.java</exclude> </excludes> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>  

 

resources/hibernate.cfg.xml:

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory name="sessionFactory"> <!-- 指定连接数据库所用的驱动 --> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <!-- 指定连接数据库的url,hibernate连接的数据库名 --> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:XE</property> <property name="hibernate.connection.useUnicode">true</property> <property name="hibernate.connection.characterEncoding">gbk</property> <!-- 指定连接数据库的用户名 --> <property name="hibernate.connection.username">system</property> <!-- 指定连接数据库的密码 --> <property name="hibernate.connection.password">password</property> <!-- 指定连接池里最大连接数 --> <property name="hibernate.c3p0.max_size">20</property> <!-- 指定连接池里最小连接数 --> <property name="hibernate.c3p0.min_size">5</property> <!-- 指定连接池里连接的超时时长,以秒为单位 --> <property name="hibernate.c3p0.timeout">120</property> <!-- 指定连接池里最大缓存多少个Statement对象 --> <property name="hibernate.c3p0.max_statements">100</property> <!-- 每隔XX秒检查连接池里的空闲连接 ,单位是秒 --> <property name="hibernate.c3p0.idle_test_period">120</property> <!-- 当连接池里面的连接用完的时候,C3P0一次获取的新的连接数 --> <property name="hibernate.c3p0.acquire_increment">2</property> <!-- 指定数据库方言 --> <property name="dialect">org.hibernate.dialect.OracleDialect</property> <!-- 显示Hibernate持久化操作所生成的SQL --> <property name="show_sql">true</property> <!-- 将SQL脚本进行格式化后再输出 --> <property name="hibernate.format_sql">true</property> <!-- 罗列所有的映射文件 --> <mapping resource="pojo/User.hbm.xml" /> <mapping resource="pojo/Address.hbm.xml" /> </session-factory> </hibernate-configuration>  

 

pojo/User.java:

package pojo; public class User { private String id; private String userName; private String password; private String email; private Address address; public String getId() { return id; } @SuppressWarnings("unused") private void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Address getAddress() { return address; } //双向关联 public void setAddress(Address address) { this.address = address; address.setUser(this); } }  

 

pojo/User.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="pojo"> <class name="User" table="MYUSER" dynamic-insert="true" dynamic-update="true"> <id name="id" column="ID" type="string"> <generator class="uuid.hex" /> </id> <property name="userName" column="USERNAME" type="string"/> <property name="password" column="PASSWORD" type="string"/> <property name="email" column="EMAIL" type="string"/> <!-- 联结表映射 ,注意optional属性,unique,cascade,not-nll属性 --> <join table="USER_ADDRESS" optional="true"> <key column="USER_ID"/> <many-to-one name="address" column="ADDRESS_ID" not-null="true" unique="true" cascade="save-update"/> </join> </class> </hibernate-mapping>

 

pojo/Address.java:

package pojo; public class Address { private String id; private String street; private String zipCode; private String city; private User user; public String getId() { return id; } @SuppressWarnings("unused") private void setId(String id) { this.id = id; } 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 String getCity() { return city; } public void setCity(String city) { this.city = city; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }

 

pojo/Address.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="pojo"> <class name="Address" table="ADDRESS" dynamic-insert="true" dynamic-update="true"> <id name="id" column="ID" type="string"> <generator class="uuid.hex" /> </id> <property name="street" column="STREET" type="string"/> <property name="zipCode" column="ZIPCODE" type="string"/> <property name="city" column="CITY" type="string"/> <!-- 联结表映射 ,注意 inverse属性 --> <join table="USER_ADDRESS" inverse="true"> <key column="ADDRESS_ID"/> <many-to-one name="user" column="USER_ID"/> </join> </class> </hibernate-mapping>

 

util/HibernateUtil.java:

package util; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static SessionFactory sessionFactory; static{ try { sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable e) { throw new ExceptionInInitializerError(e); } } public static SessionFactory getSessionFactory(){ return sessionFactory; } public static void shutdown(){ getSessionFactory().close(); } }

 

util/Manager.java:

package util; import org.hibernate.Session; import org.hibernate.Transaction; import pojo.Address; import pojo.User; public class Manager { public static void main(String[] args) { Address address = new Address(); address.setCity("guangzhou"); address.setStreet("北京路"); address.setZipCode("510000"); User user = new User(); user.setUserName("fhd"); user.setPassword("000000"); user.setEmail("[email protected]"); user.setAddress(address); Session session = HibernateUtil.getSessionFactory().openSession(); Transaction transaction = session.beginTransaction(); session.save(user); transaction.commit(); session.close(); } }

 

表结构:

MYUSER表: ID, USERNAME, PASSWORD, EMAIL ADDRESS表: ID, STREET, ZIPCODE, CITY USER_ADDRESS表: USER_ID, ADDRESS_ID

 

输出sql与日志:

Hibernate: insert into ADDRESS (STREET, ZIPCODE, CITY, ID) values (?, ?, ?, ?) Hibernate: insert into MYUSER (USERNAME, PASSWORD, EMAIL, ID) values (?, ?, ?, ?) Hibernate: insert into USER_ADDRESS (ADDRESS_ID, USER_ID) values (?, ?)

 

 

 

上例是以双向关联为例的,当然它也可以单向关联。

 

 

以User.hbm.xml为例:

因为必须用外键列映射关联,因此在User.hbm.xml中你需要<many-to-one>映射元素。然而,外键列不在MYUSER表中,而在USER_ADDRESS表中,因此可以通过<join>映射元素把它移到那里。这里为什么不能用<one-to-one>?可能是因为常规的<one-to-one>不知道任何有关联结表的信息

 

联结表有两个外键列,ADDRESS_ID(引用ADDRESS表的主键)和USER_ID(引用MYUSER表的主键).因为USER_ID是主键,所以它是唯一的,在User.hbm.xml中<many-to-one>中使用了unique="true",所以ADDRESS_ID也是唯一的,这样就保证了User与Address之间的一对一关联。

 

 

通过在<join>映射中设置optional="true",告诉hibernate它应该只有当这个映射的属性为非空时,才把行插入到联结表中。但是如果必须插入行,<many-to-one>上的not null约束就得到了应用。

 

 

可以在另一端Address.hbm.xml上使用相同的方法,把这个关联映射为双向。然而,可选的一对一关联大多数时候都是单向的。

 

你可能感兴趣的:(Hibernate高级实体关联映射之单值的实体关联(用联结表映射))