Hibernate高级实体关联映射之多值的实体关联(一对多关联,使用list)

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; import java.util.ArrayList; import java.util.List; public class User { private String id; private String userName; private String password; private String email; //使用list映射 private List<Address> addressList = new ArrayList<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 List<Address> getAddressList() { return addressList; } public void setAddressList(List<Address> addressList) { this.addressList = addressList; } //双向关联 public void addAddress(Address address){ this.addressList.add(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"/> <!-- 注意这里 ,不可用inverse="true"--> <list name="addressList" cascade="save-update"> <!-- USER_ID,不可为空,所以添加not-null='true',该外键可以禁止更新,所以update='false' --> <key column="USER_ID" not-null="true" update="false"/> <list-index column="ADDRESS_INDEX"/> <one-to-many class="Address"/> </list> </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"/> <!-- 注意这里,insert="false",update="false"都不可缺少 --> <many-to-one name="user" column="USER_ID" class="User" not-null="true" insert="false" update="false"/> </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.addAddress(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_ID, ADDRESS_INDEX 

 

输出sql:

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

 

 

 

 

注意:User.hbm.xml中<list>不可以用inverse="true",否则hibernate会忽略反向集合的状态。这一次,集合包含了正确地更新数据库所需的信息:它的元素的位置,因此不可用inverse="true",不然ADDRESS表中的索引列ADDRESS_INDEX就没有值了。

 

而在另一端,Address.hbm.xml中,<many-to-one>的多对一映射没有inverse="true"属性,那么就需要添加insert="false",

update="false"这两个属性来模拟inverse="true",缺一不可。

 

设置insert和update为false具有预期的效果。如前所述,这两个属性一起使用,实际上使属性变成了只读。关联的这一端因此被任何写操作忽略,如果从set或者bag转换到list(或者任何其他被索引的集合),这是个必要条件。

 

还要注意,User.hbm.xml中<list>元素中的<key>子元素,设置update="false",避免不必要的更新操作。

 

你可能感兴趣的:(Hibernate高级实体关联映射之多值的实体关联(一对多关联,使用list))