欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hibernate基于连接表的一对多单向关联

程序员文章站 2022-05-23 21:25:44
...

基于连接表,顾名思义就是需要建立中间表来保存两个表的关联关系。与基于外键的一对多关联关系不同的是多了一个保存外键关系的关联表,通过关联表维护两个实体之间的关系。


同时,既然是一对多,一端的Set集合肯定也是少不了的,那么在一端的hbm中,肯定也会有<set>标签出现。

 

一个Person有多个地址,建立3表,连接表jointable保存2个实体表的主键,jointable维护实体表的关联关系。
Person.java实体类中使用集合Set,保存多端的关系,并在Person.hbm.xml文件中配置关联关系。

 

 

 

创建数据库脚本如下:(参看附件)

 

-- MySQL dump 10.13  Distrib 5.1.55, for Win32 (ia32)
--
-- Host: localhost    Database: hibernate_demo
-- ------------------------------------------------------
-- Server version	5.1.55-community

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `address`
--

DROP TABLE IF EXISTS `address`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `address` (
  `addressId` int(11) NOT NULL AUTO_INCREMENT,
  `item` varchar(30) NOT NULL,
  PRIMARY KEY (`addressId`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `address`
--

LOCK TABLES `address` WRITE;
/*!40000 ALTER TABLE `address` DISABLE KEYS */;
INSERT INTO `address` VALUES (1,'address_no2'),(2,'address_no1');
/*!40000 ALTER TABLE `address` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `person`
--

DROP TABLE IF EXISTS `person`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `person` (
  `personid` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) NOT NULL,
  `sex` varchar(10) NOT NULL,
  PRIMARY KEY (`personid`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `person`
--

LOCK TABLES `person` WRITE;
/*!40000 ALTER TABLE `person` DISABLE KEYS */;
INSERT INTO `person` VALUES (1,10,'M');
/*!40000 ALTER TABLE `person` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `personadd`
--

DROP TABLE IF EXISTS `personadd`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `personadd` (
  `pid` int(11) NOT NULL,
  `aid` int(11) NOT NULL,
  KEY `pid` (`pid`),
  KEY `aid` (`aid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `personadd`
--

LOCK TABLES `personadd` WRITE;
/*!40000 ALTER TABLE `personadd` DISABLE KEYS */;
INSERT INTO `personadd` VALUES (1,1),(1,2);
/*!40000 ALTER TABLE `personadd` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2012-08-09 23:04:56
 

 

 

//Address.java

 

public class Address implements java.io.Serializable {

	// Fields

	private Integer addressId;
	private String item;

 

 

//Person.java

public class Person implements java.io.Serializable {

	// Fields

	private Integer personid;
	private Integer age;
	private String sex;
	private Set<Address> address = new HashSet<Address>();

 

//Person.hbm.xml

    	<!-- 基于连接表的一对多单项关联 -->
    	<!-- set name表示Person表中的Address集合,table是关联表名,cascade级联操作 -->
    	<!-- key column是一端主键在关联表中的外键名 -->
    	<!-- many-to-many column是多端主键在关联表中的外键名 -->
    	<set name="address" table="personadd" cascade="save-update">
        	<key column="pid"/>
        	<many-to-many column="aid"
            	unique="true"
            	class="com.v512.examples.Address"/>
    	</set>

 


保存数据

//HibernateTest.java

 

	public static void addInfo()
	{
		Address ad1 = new Address();
		ad1.setItem("address_no1");
		Address ad2 = new Address();
		ad2.setItem("address_no2");
		
		Person person = new Person();
		person.setAge(10);
		person.setSex("M");
		
		Set<Address> address = new HashSet<Address>();
		address.add(ad1);
		address.add(ad2);
		person.setAddress(address);
		
		
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = session.beginTransaction();
		//启用级联操作
		session.save(person);
//		session.save(ad1);
//		session.save(ad2);
		tx.commit();
		session.close();
		HibernateUtil.shutdown();

	}

 

 

 

操作信息如下: 

 

22:59:30,843 DEBUG ConnectionManager:444 - opening JDBC connection
22:59:30,843 DEBUG JDBCTransaction:87 - current autocommit status: false
22:59:30,843 DEBUG IncrementGenerator:104 - fetching initial value: select max(personid) from person
22:59:30,843 DEBUG AbstractBatcher:410 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
22:59:30,859 DEBUG SQL:111 - 
    select
        max(personid) 
    from
        person
Hibernate: 
    select
        max(personid) 
    from
        person
22:59:30,859 DEBUG IncrementGenerator:119 - first free id: 1
22:59:30,859 DEBUG AbstractBatcher:418 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:59:30,875 DEBUG AbstractSaveEventListener:135 - generated identifier: 1, using strategy: org.hibernate.id.IncrementGenerator
22:59:30,890 DEBUG IncrementGenerator:104 - fetching initial value: select max(addressId) from address
22:59:30,890 DEBUG AbstractBatcher:410 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
22:59:30,890 DEBUG SQL:111 - 
    select
        max(addressId) 
    from
        address
Hibernate: 
    select
        max(addressId) 
    from
        address
22:59:30,890 DEBUG IncrementGenerator:119 - first free id: 1
22:59:30,890 DEBUG AbstractBatcher:418 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:59:30,937 DEBUG AbstractSaveEventListener:135 - generated identifier: 1, using strategy: org.hibernate.id.IncrementGenerator
22:59:30,937 DEBUG AbstractSaveEventListener:135 - generated identifier: 2, using strategy: org.hibernate.id.IncrementGenerator
22:59:30,937 DEBUG JDBCTransaction:134 - commit
22:59:30,937 DEBUG AbstractFlushingEventListener:134 - processing flush-time cascades
22:59:30,937 DEBUG AbstractFlushingEventListener:177 - dirty checking collections
22:59:30,937 DEBUG Collections:199 - Collection found: [com.v512.examples.Person.address#1], was: [<unreferenced>] (initialized)
22:59:30,984 DEBUG AbstractFlushingEventListener:108 - Flushed: 3 insertions, 0 updates, 0 deletions to 3 objects
22:59:30,984 DEBUG AbstractFlushingEventListener:114 - Flushed: 1 (re)creations, 0 updates, 0 removals to 1 collections
22:59:30,984 DEBUG Printer:106 - listing entities:
22:59:30,984 DEBUG Printer:113 - com.v512.examples.Person{sex=M, address=[com.v512.examples.Address#1, com.v512.examples.Address#2], age=10, personid=1}
22:59:30,984 DEBUG Printer:113 - com.v512.examples.Address{item=address_no1, addressId=2}
22:59:30,984 DEBUG Printer:113 - com.v512.examples.Address{item=address_no2, addressId=1}
22:59:30,984 DEBUG AbstractBatcher:410 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
22:59:30,984 DEBUG SQL:111 - 
    insert 
    into
        hibernate_demo.person
        (age, sex, personid) 
    values
        (?, ?, ?)
Hibernate: 
    insert 
    into
        hibernate_demo.person
        (age, sex, personid) 
    values
        (?, ?, ?)
22:59:30,984 DEBUG AbstractBatcher:66 - Executing batch size: 1
22:59:30,984 DEBUG AbstractBatcher:418 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:59:30,984 DEBUG AbstractBatcher:410 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
22:59:30,984 DEBUG SQL:111 - 
    insert 
    into
        hibernate_demo.address
        (item, addressId) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        hibernate_demo.address
        (item, addressId) 
    values
        (?, ?)
22:59:31,000 DEBUG AbstractBatcher:248 - reusing prepared statement
22:59:31,000 DEBUG SQL:111 - 
    insert 
    into
        hibernate_demo.address
        (item, addressId) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        hibernate_demo.address
        (item, addressId) 
    values
        (?, ?)
22:59:31,000 DEBUG AbstractBatcher:66 - Executing batch size: 2
22:59:31,000 DEBUG AbstractBatcher:418 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:59:31,000 DEBUG AbstractCollectionPersister:1112 - Inserting collection: [com.v512.examples.Person.address#1]
22:59:31,000 DEBUG AbstractBatcher:410 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
22:59:31,000 DEBUG SQL:111 - 
    insert 
    into
        personadd
        (pid, aid) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        personadd
        (pid, aid) 
    values
        (?, ?)
22:59:31,000 DEBUG AbstractBatcher:248 - reusing prepared statement
22:59:31,000 DEBUG SQL:111 - 
    insert 
    into
        personadd
        (pid, aid) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        personadd
        (pid, aid) 
    values
        (?, ?)
22:59:31,000 DEBUG AbstractCollectionPersister:1194 - done inserting collection: 2 rows inserted
22:59:31,000 DEBUG AbstractBatcher:66 - Executing batch size: 2
22:59:31,000 DEBUG AbstractBatcher:418 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:59:31,000 DEBUG JDBCTransaction:147 - committed JDBC Connection
22:59:31,000 DEBUG ConnectionManager:427 - aggressively releasing JDBC connection
22:59:31,000 DEBUG ConnectionManager:464 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
22:59:31,000  INFO SessionFactoryImpl:853 - closing
22:59:31,000  INFO DriverManagerConnectionProvider:170 - cleaning up connection pool: jdbc:mysql://localhost:3306/hibernate_demo
 

 

 

 

其他的代码都是通过myeclipse生成的,不是很麻烦。

 


刚开始大家可能会有疑惑,是呀,有3个表,为什么不建3个类,3个hbm文件呢?


事实是这样的,数据库之间的表关联关系通过外键实现,现在有了外键关系表。而实体呢?实体之间是通过集合类进行关联的,我们在Person.hbm.xml文件中配置了一对多的关联关系,自然也不同在建立什么关联关系表的映射文件了,对吧。况且,2个文件能做的事情,何必用3个文件呢。