`
Supanccy2013
  • 浏览: 223765 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

hibernate一对多 双向 关联A(无连接表)

阅读更多
一,创建映射
1,多的一段 java文件中需要有一的属性,配置文件需要用 many-to-one
2,一的一段 java文件中需要有set的多的属性,配置文件需要用 one-to-many
3,many-to-one  one-to-many的column属性值要相同。

实例:人有多个地址。
1,Person类
package com.supan.bean;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Person {
	private int id;
	private String name;
	private int age;
    private Set<Address> addresss = new HashSet<Address>();
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Set<Address> getAddresss() {
		return addresss;
	}
	public void setAddresss(Set<Address> addresss) {
		this.addresss = addresss;
	}
}

Person的配置文件
<?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 default-lazy="true" default-access="property" package="com.supan.bean" >
    <class name="Person" dynamic-update="true" dynamic-insert="true" table="myperson">
        <id name="id" column="id" type="integer">
            <generator class="native"/>
        </id>
        <property name="name" type="string" column="name" length="20"/>
        <property name="age" type="integer" column="age" length="3"/>
        <set name="addresss" inverse="true">
             <key column="personid"/>
             <one-to-many class="Address"/>
        </set>
    </class>
</hibernate-mapping>

2,Address类
package com.supan.bean;
public class Address {
	private int id;
	private String name;
	private String info;
    private String remark;
    private Person person;
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	public String getRemark() {
		return remark;
	}
	public void setRemark(String remark) {
		this.remark = remark;
	}
}

Address类的配置文件:
<?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 default-lazy="true" default-access="property" package="com.supan.bean" >
    <class name="Address" dynamic-update="true" dynamic-insert="true" table="address">
        <id name="id" column="id" type="integer">
            <generator class="native"/>
        </id>
        <property name="name" type="string" column="NAME" length="20"/>
        <property name="info" type="string" column="INFO" length="30"/>
        <property name="remark" type="string" column="REMARK" length="30"/>
        <many-to-one name="person" class="Person" column="personid" not-null="true"></many-to-one>
    </class>
</hibernate-mapping>


二:一对多的插入
一对多双向关联效率最高的插入方法:
1,先持久化Person对象,因为我们希望我们在持久化Address的时候已经有Person可以被
Address关联(关联关系由多的一方维护)。
2,先从Address 设置Person和Address的关系,再持久化Address对象,因为如果顺序颠倒过来,我们在持久化Address的时候还有关联Person和Address的关系,这个时候Address已经被持久化了,等要设置关联关系的时候hibernate还要发送一个udpate语句,影响效率。  当前如果你执意要颠倒过来的话就必须设置Address配置文件中many-to-one标签的nut-null为false,否则会报错
3,不要通过Person对象来设置关联关系,因为我们已经在Person映射文件的Set标签中已经制定了inverse 为true
package com.supan.test;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.supan.bean.Address;
import com.supan.bean.Person;
public class HibernateCrudTest  extends TestCase {
    public void testInsert(){
		Configuration config = new Configuration().configure();
		SessionFactory sf = config.buildSessionFactory();
		Session sess = sf.openSession();
		Transaction tx = (Transaction) sess.beginTransaction();
		
		Person person = new Person();
		person.setName("陈超阳");
		person.setAge(27);
		sess.save(person);
		
		Address address = new Address();
		address.setName("吉祥地铁站");
		address.setInfo("那是我第一次来深圳住的地方");
		address.setRemark("目前已经不再那里居住了");
		address.setPerson(person);
		sess.persist(address);
		
		Address address2 = new Address();
		address2.setName("坂田五里围");
		address2.setInfo("我目前居住的地方");
		address2.setRemark("附近的消费很低");
		address2.setPerson(person);
		sess.persist(address2);
		
		tx.commit();
		sess.close();
    }
}



二:一对多的查询
1,查询一的对象,会自动的把它关联的多的一段的都查出来,一般需要设置懒加载为true
public void testQuery(){
		Configuration config = new Configuration().configure();
		SessionFactory sf = config.buildSessionFactory();
		Session sess = sf.openSession();
		Transaction tx = (Transaction) sess.beginTransaction();
		String hql = "from Person";
		List<Person> persons = sess.createQuery(hql).list();
		for(Person person : persons){
			for(Address address : person.getAddresss()){
				System.out.println(address.getName());
			}
		}
		tx.commit();
		sess.close();
}

2,查询多的一段,会自动的把一的一段查询出来,懒加载与否无所谓
public void testQuery2(){
		Configuration config = new Configuration().configure();
		SessionFactory sf = config.buildSessionFactory();
		Session sess = sf.openSession();
		Transaction tx = (Transaction) sess.beginTransaction();
		String hql = "from Address";
		List<Address> address = sess.createQuery(hql).list();
		for(Address tempaddress : address){
			System.out.println(tempaddress.getPerson().getName());
		}
		tx.commit();
		sess.close();
}


3,关联查询
1,隐式关联查询 用.
    public void testQuery3(){
		Configuration config = new Configuration().configure();
		SessionFactory sf = config.buildSessionFactory();
		Session sess = sf.openSession();
		Transaction tx = (Transaction) sess.beginTransaction();
		String hql = "from Address ad where ad.person.name = :myname ";
		List<Address> address = sess.createQuery(hql).setString("myname", "陈超阳").list();
		for(Address tempaddress : address){
			System.out.println(tempaddress.getPerson().getName());
		}
		tx.commit();
		sess.close();
}

hibernate发送的查询sql(其实是自然连接),特别注意:查询出来的是Address实体的list列表。
Hibernate: 
    select
        address0_.id as id1_,
        address0_.NAME as NAME1_,
        address0_.INFO as INFO1_,
        address0_.REMARK as REMARK1_,
        address0_.personid as personid1_ 
    from
        address address0_,
        myperson person1_ 
    where
        address0_.personid=person1_.id 
        and person1_.name=?
Hibernate: 
    select
        person0_.id as id0_0_,
        person0_.name as name0_0_,
        person0_.age as age0_0_ 
    from
        myperson person0_ 
    where
        person0_.id=?

2,内连接 inner join
    public void testQuery3(){
		Configuration config = new Configuration().configure();
		SessionFactory sf = config.buildSessionFactory();
		Session sess = sf.openSession();
		Transaction tx = (Transaction) sess.beginTransaction();
		String hql = "from Address a inner join a.person p where p.name = :myname ";
		List result = sess.createQuery(hql).setString("myname", "陈超阳").list();
		for(int i=0; i< result.size(); i++){
			Object[] temp = (Object[])result.get(i);
			  Address addressTemp = (Address)temp[0];
			  System.out.println(addressTemp.getName());
			  Person personTemp = (Person)temp[1];
			  System.out.println(personTemp.getName());
		}
		tx.commit();
		sess.close();
    }

hibernate发送的sql语句,特别注意:查询出来的是address,person组合的实体
Hibernate:
    select
        address0_.id as id1_0_,
        person1_.id as id0_1_,
        address0_.NAME as NAME1_0_,
        address0_.INFO as INFO1_0_,
        address0_.REMARK as REMARK1_0_,
        address0_.personid as personid1_0_,
        person1_.name as name0_1_,
        person1_.age as age0_1_
    from
        address address0_
    inner join
        myperson person1_
            on address0_.personid=person1_.id
    where
        person1_.name=?
关于隐式连接查询,和显示连接查询的结果是截然不同的:
1,当hql语句中省略了select关键字时,使用隐式连接查询返回的结果是多个被查询实体组成的集合,
2,当使用显示连接省略select关键字时候,返回的结果也是集合,但是集合元素是被查询持久的对象,所有被关联的持久化对象所组成的数组,如上面的sql语句所示,它同事选择了Person,address表中的所有数据列,查询到的结果集的每条记录既包含了Person实体的全部属性,也包含了Address实体的全部属性,。hibernate会把每条记录封装成一个集合元素,用属于Person的属性创建Person对象,用属于Address的属性创建Address对象,多个持久化实体最后封装成一个数组。

三,一对多删除
1,删除一的时候
一的配置文件中有:
<set name="addresss" inverse="true" >
             <key column="personid"/>
             <one-to-many class="Address"/>
</set>
public void testDelete(){
		Configuration config = new Configuration().configure();
		SessionFactory sf = config.buildSessionFactory();
		Session sess = sf.openSession();
		Transaction tx = (Transaction) sess.beginTransaction();
		Person person = (Person)sess.get(Person.class, 1);
		sess.delete(person);
		tx.commit();
		sess.close();
}

报错如下:
java.lang.IllegalArgumentException: attempt to create delete event with null entity
at org.hibernate.event.DeleteEvent.<init>(DeleteEvent.java:47)
at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:772)
at com.supan.test.HibernateCrudTest.testDelete(HibernateCrudTest.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
原因:没有设置级联,删除一个时候,hibernate查到了这个一有多个Address引用,所以不能删除,
解决办法:
在Person的配置文件中添加:
        <set name="addresss" inverse="true" cascade="all" >
             <key column="personid"/>
             <one-to-many class="Address"/>
        </set>

设置之后删除一个一端,会连带多的一端一起删掉
2,删除多的一段
如果多的一端的many-to-one标签没有设置cascade="all"那么仅仅会删除多的一端,如果设置了cascade="all"那么就会连带一的一端也会删除。hibernate真是牛逼。
public void testDelete2(){
Configuration config = new Configuration().configure();
SessionFactory sf = config.buildSessionFactory();
Session sess = sf.openSession();
Transaction tx = (Transaction) sess.beginTransaction();
Address address = (Address)sess.get(Address.class, 9);
sess.delete(address);
tx.commit();
sess.close();
}



分享到:
评论

相关推荐

    hibernate多对多双向关联

    **标题解析:**“hibernate多对多双向关联” 在Java编程中,Hibernate是一个流行的ORM(对象关系映射)框架,它允许开发者用面向对象的方式处理数据库操作。"多对多双向关联"是Hibernate中一种关系映射类型,涉及两...

    Hibernate ORM - 一对多双向连接表关联关系

    "HibernateORM"可能是包含有关Hibernate ORM框架的详细信息的文件夹或压缩包,里面可能包含示例代码、教程文档或其他资源,用于辅助学习和理解Hibernate ORM的一对多双向关联。 **知识点详解:** 1. **Hibernate ...

    Hibernate ORM - 多对多双向连接表关联关系

    在Hibernate中,实现多对多双向关联主要涉及以下步骤: 1. **配置实体类**:首先,你需要为每个参与关联的实体定义一个Java类,并添加相应的属性。例如,对于“学生-课程”关系,可以有`Student`和`Course`类,它们...

    hibernate双向一对多关联映射(注解版)

    在Java的持久化框架Hibernate中,双向一对多关联映射是一种常见的关系映射方式,它模拟了数据库中的外键关联,使得一个实体可以拥有多个另一个实体的实例。在这个注解版的实现中,我们将深入探讨如何使用Hibernate的...

    myeclipse试用小记----Hibernate多对一双向关联(2)

    首先,我们需要了解在Hibernate中多对一和一对多关联的概念。多对一关联意味着在数据库中,一个实体(表)可以与多个其他实体相关联,而在这些其他实体中,每个实体最多只能与一个原实体关联。例如,一个部门可以有...

    Hibernate关联映射

    9. Hibernate 一对一外键双向关联、主键双向关联、连接表双向关联、一对多外键双向关联、一对多连接表双向关联、多对多双向关联: 这些关联方式与单向关联类似,区别在于两个实体类都知道彼此的关联。在双向关联中...

    Hibernate Annotation 共享主键一对一双向关联

    在实际的项目开发中,我们经常遇到各种各样的关联关系,比如一对一、一对多、多对一、多对多等。本文将详细讲解“Hibernate Annotation 中的共享主键一对一双向关联”。 首先,我们需要理解什么是共享主键(Shared ...

    hibernate双向多对多关联映射(注解版)

    多对多关系通常需要一个中间表来存储两个实体的关联信息,但在Hibernate中,我们不需要手动创建这个中间表。`@JoinTable`注解可以用来定义中间表的详细信息,包括表名、连接字段等。 3. **关系的维护**: 在双向...

    hibernate 多表关联 中间表

    首先,我们需要理解Hibernate中的两种主要关联类型:一对一(One-to-One)和一对多(One-to-Many)。而多对多关系是通过在两个参与实体之间创建一个额外的中间表来实现的,这个中间表通常包含两个外键,分别指向原表...

    hibernate多对多关联映射(单项关联)

    在Java的持久化框架Hibernate中,多对多关联映射是一种常见的关系模型,它用于处理两个实体类之间存在多个对应关系的情况。这篇博客"hibernate多对多关联映射(单项关联)"深入探讨了如何在Hibernate中实现这种映射...

    hibernate一对多与多对一

    本篇文章将详细讲解"hibernate一对多与多对一"的关系映射概念,以及如何在实际开发中进行配置和使用。 首先,我们来看一下“一对多”关系。在现实世界中,这种关系可以对应到例如一个班级有多个学生,或者一个人...

    多对多双向关联

    首先,我们来看如何在Java中使用JPA(Java Persistence API)或Hibernate(一个流行的JPA实现)来设置多对多双向关联。双向关联意味着两个实体类都将持有对彼此的引用。例如,考虑一个“学生”和“课程”的场景,每...

    hibernate基于主外键的一对多/多对一关联

    总结起来,Hibernate中的一对多/多对一关联是通过主外键映射来实现的,通过注解和配置文件定义实体间的关联关系,利用懒加载或立即加载策略控制数据获取,同时要注意双向关联的维护和级联操作的设置,以确保数据的...

    Hibernate关于注解的一对多,多对多,一对一

    本篇文章将深入探讨Hibernate中注解的一对多、多对多和一对一关系映射。 ### 一对多关系 在现实生活中,例如一个班级有一个班主任,而班主任可以管理多个学生,这就是典型的“一对多”关系。在Hibernate中,我们...

    hibernate实例(一对多,多对一)

    在这个“hibernate实例(一对多,多对一)”的主题中,我们将深入探讨两种重要的关联关系:一对一(One-to-One)和一对多(One-to-Many)。 **一对一关联(One-to-One)** 在一对一关联中,一个实体与另一个实体之间...

    hibernate实体关联关系映射

    本文旨在深入探讨Hibernate中的实体关联关系映射技术,主要包括一对一、一对多、多对多等不同类型的关联关系及其在实际开发中的应用技巧。通过本文的学习,开发者可以更好地理解和掌握Hibernate框架下的实体关联关系...

    Hibernate 一对一,一对多,多对多例子

    4. **双向关联**:在一对一和一对多关联中,关联可以是单向或双向的。双向关联意味着两个实体都能访问到彼此,需要在双方都添加相应的注解。例如,对于一对一关联,需要在双方都使用`@OneToOne`,对于一对多,需要在...

    hibernate多对多

    在Java的持久化框架Hibernate中,多对多(Many-to-Many)关系是数据库中常见的关联类型,它允许一个实体实例对应多个其他实体实例,反之亦然。在本案例中,我们将深入探讨如何使用Hibernate来处理多对多的关系映射,...

    Hibernate ORM - 多对多双向中间实体关联关系

    本文将深入探讨Hibernate ORM中的一个关键概念:多对多双向中间实体关联关系。这种关联关系在实际业务场景中非常常见,比如用户与角色、课程与学生之间的关联等。 首先,多对多关联意味着两个实体类之间存在多个...

Global site tag (gtag.js) - Google Analytics