備註:本文有參考hibernate多對多關係配置--增刪改查
==========================================================
==========================================================
1.項目結構:
========================
2.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>com.lin</groupId>
<artifactId>Hibernate_ManyToMany</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.10.Final</version>
</dependency>
<!-- MySQL驅動包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<!-- jstl、servlet-api、junit -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
========================
3.實體類和映射文件
Person.java
package com.lin.domain;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* 人 實體類
* */
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private String personName;
private String password;
//一個人可以有多個地址,一個地址可以對應多個人。所以 人跟地址 是多對多的關聯關係。
private Set<Address> addresss = new HashSet<Address>(0);
public Person() {
super();
}
public Person(Long personId, String personName, String password) {
super();
this.personId = personId;
this.personName = personName;
this.password = password;
}
public Long getPersonId() {
return personId;
}
public void setPersonId(Long personId) {
this.personId = personId;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Address> getAddresss() {
return addresss;
}
public void setAddresss(Set<Address> addresss) {
this.addresss = addresss;
}
@Override
public String toString() {
return "Person [personId=" + personId + ", personName=" + personName
+ ", password=" + password + "]";
}
}
Person.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 package="com.lin.domain">
<!-- name指定持久化類的類名,table指定數據表的表名 -->
<class name="Person" table="table_person">
<id name="personId" column="person_id">
<generator class="native"/>
</id>
<property name="personName" column="person_name"></property>
<property name="password" column="password"></property>
<!--映射集合屬性,關聯到持久化類,table="table_person_address"指定了中間表的名字-->
<set name="addresss" table="table_person_address" inverse="true">
<key>
<!--column屬性指定中間表中關聯當前實體類的列名-->
<column name="person_id"/>
</key>
<!--column屬性指定中間表中關聯本實體的外鍵-->
<many-to-many class="Address" column="address_id"/>
</set>
</class>
</hibernate-mapping>
Address.java
package com.lin.domain;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Address implements Serializable{
private static final long serialVersionUID = 1L;
private Long addressId;
private String addressInfo;
//一個地址可以對應多個人,一個人可以有多個地址。所以 地址跟人 是多對多的關聯關係。
private Set<Person> persons = new HashSet<Person>(0);
public Address() {
super();
}
public Address(Long addressId, String addressInfo) {
super();
this.addressId = addressId;
this.addressInfo = addressInfo;
}
public Long getAddressId() {
return addressId;
}
public void setAddressId(Long addressId) {
this.addressId = addressId;
}
public String getAddressInfo() {
return addressInfo;
}
public void setAddressInfo(String addressInfo) {
this.addressInfo = addressInfo;
}
public Set<Person> getPersons() {
return persons;
}
public void setPersons(Set<Person> persons) {
this.persons = persons;
}
@Override
public String toString() {
return "Address [addressId=" + addressId + ", addressInfo="
+ addressInfo + "]";
}
}
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 package="com.lin.domain">
<!-- name指定持久化類的類名,table指定數據表的表名 -->
<class name="Address" table="table_address">
<id name="addressId" column="address_id">
<generator class="native"/>
</id>
<property name="addressInfo" column="address_info"></property>
<!--映射集合屬性,關聯到持久化類,table="table_person_address"指定了雙向多對多映射中間表的名字-->
<set name="persons" table="table_person_address">
<key>
<!--column屬性指定中間表中關聯當前實體類的列名-->
<column name="address_id"/>
</key>
<!--column屬性指定中間表中關聯本實體的外鍵-->
<many-to-many class="Person" column="person_id"/>
</set>
</class>
</hibernate-mapping>
========================
4.Hibernate配置文件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">
<!--
Hibernate配置文件包含了連接持久層與映射文件所需的基本信息。
(Hibernate配置文件主要用來配置數據庫連接以及Hibernate運行時所需的各個屬性的值。)
-->
<hibernate-configuration>
<session-factory>
<!-- 數據庫連接設置 -->
<!-- 配置數據庫JDBC驅動 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 配置數據庫連接URL -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<!-- 配置數據庫用戶名 -->
<property name="hibernate.connection.username">root</property>
<!-- 配置數據庫密碼 -->
<property name="hibernate.connection.password">000000</property>
<!-- 配置JDBC內置連接池 -->
<property name="connection.pool_size">1</property>
<!-- 配置數據庫方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 配置Hibernate採用何種方式生成DDL語句 -->
<!-- update表示檢測實體類的映射配置和數據庫的表結構是否一致 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 輸出運行時生成的SQL語句 -->
<property name="show_sql">true</property>
<!-- 列出所有的映射文件 -->
<mapping resource="hibernate/mappings/Person.hbm.xml" />
<mapping resource="hibernate/mappings/Address.hbm.xml" />
</session-factory>
</hibernate-configuration>
========================
5.Hibernate工具類
package com.lin.utils;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static Configuration configuration;
//創建線程局部變量threadLocal,用來保存Hibernate的Session
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
//使用靜態代碼塊初始化Hibernate
static{
try{
//如果不指定hibernate的配置文件位置,那麼它會默認到classpath路徑下查找名爲hibernate.cfg.xml的文件
Configuration cfg = new Configuration().configure("/hibernate/hibernate.cfg.xml");
//創建SessionFactory
sessionFactory = cfg.buildSessionFactory();
}catch(Throwable ex){
throw new ExceptionInInitializerError(ex);
}
}
//獲得SessionFactory
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
//獲得ThreadLocal對象管理的Session實例
public static Session getSession() throws HibernateException {
Session session = (Session)threadLocal.get();
if(session == null || session.isOpen()){
if(sessionFactory == null){
rebuildSessionFactory();
}
//通過SessionFactory對象創建Session對象
session = (sessionFactory != null)?sessionFactory.openSession():null;
//將新打開的Session實例保存到線程局部變量threadLocal中
threadLocal.set(session);
}
return session;
}
//關閉Session實例
public static void closeSession() throws HibernateException {
//從線程局部變量threadLocal中獲取之前存入的Session實例
Session session = (Session)threadLocal.get();
threadLocal.set(null);
if(session != null){
session.close();
}
}
//重建SessionFactory
public static void rebuildSessionFactory() {
try{
configuration.configure("/hibernate/hibernate.cfg.xml");
sessionFactory = configuration.buildSessionFactory();
}catch(Exception e){
System.out.println("Error Creating SessionFactory ");
e.printStackTrace();
}
}
//關閉緩存和連接池
public static void shutdown(){
getSessionFactory().close();
}
public static void main(String[] args){
HibernateUtil.getSession();
}
}
========================
6.測試類
①保存操作
/**
* 保存操作
* */
@Test
public void saveTest(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person person1 = new Person();
person1.setPersonName("林1");
person1.setPassword("111111");
Person person2 = new Person();
person2.setPersonName("林2");
person2.setPassword("222222");
Address address1 = new Address();
address1.setAddressInfo("地址1");
Address address2 = new Address();
address2.setAddressInfo("地址2");
Address address3 = new Address();
address3.setAddressInfo("地址3");
//注意,這裏是雙向關聯,所以人要添加地址,地址也要關聯人
person1.getAddresss().add(address1);
person1.getAddresss().add(address2);
person2.getAddresss().add(address2);
person2.getAddresss().add(address3);
address1.getPersons().add(person1);
address2.getPersons().add(person1);
address2.getPersons().add(person2);
address3.getPersons().add(person2);
//地址或人,誰先保存都可以
session.save(address1);
session.save(address2);
session.save(address3);
session.save(person1);
session.save(person2);
tx.commit();
session.close();
}
測試結果:
②CRUD測試操作
package com.lin.test;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.lin.domain.Address;
import com.lin.domain.Person;
import com.lin.utils.HibernateUtil;
/**
* 多對多關聯關係的CRUD操作
* */
public class HibernateManyToManyTest {
/**
* 保存操作。
* */
@Test
public void saveTest(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person person1 = new Person();
person1.setPersonName("林1");
person1.setPassword("111111");
Person person2 = new Person();
person2.setPersonName("林2");
person2.setPassword("222222");
Address address1 = new Address();
address1.setAddressInfo("地址1");
Address address2 = new Address();
address2.setAddressInfo("地址2");
Address address3 = new Address();
address3.setAddressInfo("地址3");
//注意,這裏是雙向關聯,所以人要添加地址,地址也要關聯人
person1.getAddresss().add(address1);
person1.getAddresss().add(address2);
person2.getAddresss().add(address2);
person2.getAddresss().add(address3);
address1.getPersons().add(person1);
address2.getPersons().add(person1);
address2.getPersons().add(person2);
address3.getPersons().add(person2);
//地址或人,誰先保存都可以
session.save(address1);
session.save(address2);
session.save(address3);
session.save(person1);
session.save(person2);
tx.commit();
session.close();
}
/**
* 刪除操作 。
* */
@Test
public void deleteTest(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person person = (Person) session.get(Person.class, 1L);
//如果有關聯關係,那麼需先將關聯關係刪掉才行
Set<Address> addresss = person.getAddresss();
for(Address address: addresss){
address.getPersons().remove(person);
}
session.delete(person);
tx.commit();
session.close();
}
/**
* 更新操作。
* 更新本張表。
* */
@Test
public void updateTest(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person person = (Person) session.get(Person.class, 2L);
person.setPersonName("小林111");
session.update(person);
tx.commit();
session.close();
}
/**
* 更新操作。
* 更新關聯表。
* */
@Test
public void updateTest2(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person person = (Person) session.get(Person.class, 2L);
//下面的這個地址跟這個人是沒有關聯關係的,但是我執行更新操作後還是可以正常更新地址數據
// Address address = (Address) session.get(Address.class, 1L);
// address.setAddressInfo("泉州111");
Address address = (Address) session.get(Address.class, 2L);
address.setAddressInfo("泉州222");
person.getAddresss().add(address);
session.update(person);
tx.commit();
session.close();
}
/**
* 查詢操作。
* */
@Test
public void selectTest(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person person = (Person) session.get(Person.class, 2L);
System.out.println(person);
Set<Address> addresss = person.getAddresss();
System.out.println(addresss);
tx.commit();
session.close();
}
}
總結:從雙向的一對多,到雙向的一對一、再到雙向的多對多。最關鍵的就是實體類與數據表的映射關係xxx.hbm.xml。然後最最重要的還是雙向的一對多關聯映射超詳細的Hibernate關聯關係之雙向的一對多關聯關係的CRUD操作————學習至黑馬程序員視頻教程,這篇博文是從視屏教程上面照着代碼敲出來的,這個好好理解一下應該問題就不大了。剩下的兩個一對一, 多對多,這個是我自己經過百度、參看書上的內容以及參考上面提到的博文做出的測試,裏面功能上大概都有涉及到,但是不管從知識點還是註解上都相對沒有那麼詳細。所以一些寫的不對的地方歡迎大神指教。。。