在set集合中,如果是实体类,那么实体类必须重写equals()和hashCode()方法 !!!!
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.HashSet; import java.util.Set; public class User { private String id; private String userName; private String password; private String email; //使用set映射 private Set<Address> addressList = new HashSet<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 Set<Address> getAddressList() { return addressList; } public void setAddressList(Set<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"/> <!-- set上使用了table属性 --> <set name="addressList" table="USER_ADDRESS" cascade="save-update" inverse="true"> <key column="USER_ID"/> <many-to-many class="Address" column="ADDRESS_ID" unique="true"/> </set> </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; } //重写hashCode()方法 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((city == null) ? 0 : city.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((street == null) ? 0 : street.hashCode()); result = prime * result + ((zipCode == null) ? 0 : zipCode.hashCode()); return result; } //重写equals()方法 @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Address other = (Address) obj; if (city == null) { if (other.city != null) return false; } else if (!city.equals(other.city)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (street == null) { if (other.street != null) return false; } else if (!street.equals(other.street)) return false; if (zipCode == null) { if (other.zipCode != null) return false; } else if (!zipCode.equals(other.zipCode)) return false; return true; } }
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"/> <!-- 这里使用join --> <join table="USER_ADDRESS" optional="true"> <key column="ADDRESS_ID" not-null="true"/> <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"); Address address1 = new Address(); address1.setCity("guangzhou11"); address1.setStreet("北京路11"); address1.setZipCode("51000011"); User user = new User(); user.setUserName("fhd"); user.setPassword("000000"); user.setEmail("[email protected]"); user.addAddress(address); user.addAddress(address1); 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表: ADDRESS_ID, USER_ID
输出sql:
Hibernate: insert into MYUSER (USERNAME, PASSWORD, EMAIL, ID) values (?, ?, ?, ?) Hibernate: insert into ADDRESS (STREET, ZIPCODE, CITY, ID) (?, ?, ?, ?) Hibern ate: in sert in to USER_ADDRESS (USER_ID, ADDRESS_ID) va lues (?, ?) Hibern ate: in sert in to ADDRESS (STREET, ZIPCODE, CITY, ID) va lues (?, ?, ?, ?) Hibern ate: in sert in to USER_ADDRESS (USER_ID, ADDRESS_ID) va lues
上例中,用Set作为集合类型。集合表是联结表USER_ADDRESS;它的主键是USER_ID和ADDRESS_ID的复合。
你之前还没有见过的新映射元素是:<many-to-many>;因为常规的<one-to-many>不知道任何有关联结表的信息,因此需要它。
通过在引用目标实体表的外键列上强制unique约束,有效地强制了一对多的多样性。
在Address.hbm.xml中,使用了<join>映射。如:
<join table="USER_ADDRESS" optional="true">
<key column="ADDRESS_ID" not-null="true"/>
<many-to-one name="user" column="USER_ID"/>
</join>
这里有两个重要的细节:首先,关联是可选的,你告诉Hibernate如果被分组的属性(这里只有一个属性user)为null,就不要把行插入到联结表。第二,这是一个双向的实体关联,与往常一样,一端必须为反向的(inverse="true")。