浅谈Hibernate中映射集合属性以及主键和外键

首先说明一下什么叫主键以及外键。

主键和外键是对于数据库来说的,数据库的表才有主键外键的说法。

主键:主键是指标识某个表中唯一且非空的一条记录行的列,这个列中的值不允许有重复的值,用于确定一个表中的一条记录,实际上主键就是告诉别人:这个数据列是唯一的。

外键:引用另外一个表中的主键,在当前表中不一定为唯一的,但是在被引用表中一般唯一。对于关系型数据库来说(比如MySQL)外键是联系数据表之间的唯一方式,主要目的是控制存储在外键表中的数据。

建立外键的前提:本表的列必须与外键类型相同(外键必须是外表主键)。

例如:

表1:用户编号(主键)  用户名称  部门编号(外键)

表2:部门编号(主键)  部门名称

这里来讲:对于表1来说,用户编号是主键,对于表2来讲部门编号是主键,然后表1引用表2的主键作为外键,这样就将两个数据表关联起来了,表一中每个部门编号表二都会有个部门名称相对应。

下面开始映射集合属性:

因为关于Hibernate中映射List、Array、Set、以及Map的方式相差不大,此处仅拿映射List展开,其他稍作介绍。

Hibernate映射List集合

一:PersonList.java

Person类中除了普通属性外,还有一个List集合属性:schools,该属性对应多个学校。

package com.mao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name="personList_inf")
public class PersonList {
	//分别指定主键、主键列名、主键为自增
	@Id
	@Column(name="person_id",nullable=false)
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer id;
	@Column (name="person_name",length=50)
	private String name;
	@Lob
	@Basic(fetch=FetchType.LAZY)
	private byte[]pic;
	//通过@Temporal注解 可以完成持久化属性映射到数据库的时间格式
	@Temporal(TemporalType.DATE)
	private Date birth;
	//如果集合通过泛型指定了类型 则可以不通过targetClass指定类型
	@ElementCollection(targetClass=String.class)
	//指定保存集合的数据表 并指定外键列
	@CollectionTable(name="schools_inf",[email protected] (name="person_id",nullable=false))
	//指定保存集合元素的列为:school_name
	@Column (name="school_name")
	//映射集合元素的索引的列
	@OrderColumn(name="list_order")
	private List<String> school=new ArrayList<>();
	//相应的set、get方法
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public byte[] getPic() {
		return pic;
	}
	public void setPic(byte[] pic) {
		this.pic = pic;
	}
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public List<String> getSchool() {
		return school;
	}
	public void setSchool(List<String> school) {
		this.school = school;
	}

}

二:主程序 PersonManagerList.java

package com.mao;

import java.io.File;
import java.io.FileInputStream;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class PersonManagerList
{
	public static void main(String[]args) throws Exception{
		Configuration cof=new Configuration().configure();
		ServiceRegistryBuilder serviceRegistryBuilder=new ServiceRegistryBuilder().applySettings(cof.getProperties());
		ServiceRegistry registry=serviceRegistryBuilder.buildServiceRegistry();
		SessionFactory sf=cof.buildSessionFactory(registry);
		Session sess=sf.openSession();
		Transaction tx=sess.beginTransaction();
	    PersonList person=new PersonList();
		person.setName("VipMao");
		//创建文件 上传图片到数据库
		File file=new File("image/2.jpg");
		byte[]content=new byte[(int) file.length()];
		//创建读取数据流来读取图片对象file并存入字节数组content
		new FileInputStream(file).read(content);
		person.setPic(content);
		person.setBirth(new Date());
		person.getSchool().add("菜鸟学院");
		//保存信息并将对象持久化
		sess.save(person);
		//提交事务
		tx.commit();
		sess.close();
		sf.close();
	}
}

三:配置文件 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-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.characterEncoding">utf-8</property>
         <!-- 指定连接池最大连接数 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <!-- 指定连接池最小连接数 -->
        <property name="hibernate.c3p0.min_size">1</property>
        <!-- 指定连接池里连接超时时长 -->
        <property name="hibernate.c3p0.timeout">5000</property>
        <!-- 指定连接池里做大缓存多少个Statement对象 -->
        <property name="hibernate.c3p0.max_statements">50</property>
        <!-- 是否根据需要自动建表 -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 是否显示sql语句 -->
        <property name="show_sql">true</property>
        <!-- 将SQL脚本进行格式化后再输出 -->
        <property name="hibernate.format_sql">true</property>
        <!-- 设置连接数据库所使用的方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 罗列所有持久化类名 -->
      <!--
        <mapping class="com.mao.Person"/>
        <mapping class="com.mao.PersonMap"/>
        <mapping class="com.mao.PersonArray"/>
        <mapping class="com.mao.PersonSet"/>
         -->
        <mapping class="com.mao.PersonList"/>
    </session-factory>
</hibernate-configuration>

四:运行结果

从控制台输出的SQL语句可以看出,先在personList_inf表中插入了普通属性,然后通过外键列在schools_inf表中插入集合信息,下面数据库结果:

这样person_id是表一的主键 ,person_id也为表二的主键,然后表一把表二的主键作为外键,这样就将两个表建立起联系了,每在表一添加一个person_id的时候表二都会对应一个school_name和list_order(集合索引)。

五:映射集合常用的注解

@ElementCollection:用于映射集合属性

@CollectionTable:用于映射集合属性表,name属性指定存储集合属性表的表名,joinColumns属性映射外键列

@Column:用于映射保存集合元素的数据列

@OrderColumn:用于映射集合的索引列,像Set这种无序集合可以不用此注解

Hibernate映射Array集合

一:PersonArray.java(只给出集合部分变动)

@ElementCollection(targetClass=String.class)
	@CollectionTable(name="arraySchool_inf" ,[email protected](name="id",nullable=false))
	//指定保存集合元素的列为school_name
	@Column(name="school_name")
	//映射集合元素的索引
	@OrderColumn(name="array_order")
	private String[]school;

二:PersonManagerArray.java

 PersonArray person=new PersonArray();
		person.setName("VipMao");
		File file=new File("image/2.jpg");
		byte[]content=new byte[(int) file.length()];
		//创建读取数据流来读取图片对象file并存入字节数组content
		new FileInputStream(file).read(content);
		person.setPic(content);
		person.setBirth(new Date());
		System.out.println("日期为:"+new Date());
		String[]school=new String[3];
		school[0]="菜鸟学院";
		school[1]="小牛学院";
		school[2]="大牛学院";
		person.setSchool(school);
		sess.save(person);

三:运行结果

Hibernate映射Set集合

一:PersonSet.java

@ElementCollection
	@CollectionTable(name="schoolSet_inf" , [email protected](name="person_id",nullable=false))
	@Column(name="school_name",nullable=false)
	private Set<String>schools=new HashSet<>();

二:PersonManagerSet.java

PersonSet person=new PersonSet();
		person.setName("VipMao");
		person.setAge("24");
		person.getSchools().add("菜鸟学院");
		person.getSchools().add("小牛学院");
		person.getSchools().add("大牛学院");
		sess.save(person);

三:运行结果:

可以看出,因为Set集合的无序性,我们并没有通过@OrderColumn映射集合的索引列。

Hibernate映射Map集合

一:PersonMap.java

@ElementCollection(targetClass=Float.class)
	@CollectionTable(name="score_inf",[email protected](name="person_id",nullable=false))
	//映射保存Map key的数据列
	@MapKeyColumn(name="subject_name")
	//指定Map key的类型为String类型
	@MapKeyClass(String.class)
	//映射保存 Map value的数据列
	@Column(name="mark")
	private Map<String,Float>scores=new HashMap<>();

二:PersonManagerMap.java

PersonMap person = new PersonMap();
		person.setAge("24");
		person.setName("VipMao");
		// 向person的Map集合属性中添加key-value对
		person.getScores().put("语文" , 90f);
		person.getScores().put("英文" , 99f);
		session.save(person);

三:运行结果

最后说一下各集合的联合主键问题:

List联合主键:持久化外键列+集合元素索引列

Set联合主键:持久化外键列+Set元素列(元素列不能为空)

Map联合主键:持久化外键列+集合Key列

时间: 2024-10-13 06:39:56

浅谈Hibernate中映射集合属性以及主键和外键的相关文章

浅谈Hibernate关系映射(3)

继上篇博客 一对多关联映射(单向) 上面我们介绍了多对一,我们反过来看一对多不就是多对一吗?那还用再进行不同的映射吗?有什么差别吗?一对多和多对一映射原理是一致的,存储是相同的,也就是生成的数据库的表是一样的,他们之间不同的是维护的关系不同. 他们之间不同点是维护的关系不同 *多对一维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来. *一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来. 一个班级有多个学生,通过班级可以看到学生信息. Class

浅谈Hibernate关系映射(4)

继上篇博客 多对多关联映射(单向) 多对多对象关系映射,需要加入一张新表完成基本映射. Hibernate会自动生成中间表 Hibernate使用many-to-many标签来表示多对多的关联,多对多的关联映射,在实体类中,跟一对多一样,也是用集合来表示的. 如下图所示 通过User可以查看Role的信息 User的映射文件 <hibernate-mapping> <class name="com.bjpowernode.hibernate.User"> <

浅谈Hibernate关系映射(2)

继上篇博客 一对一关系映射:一对一关联映射在实际生活中是比较常见的,如人与身份证的关系,通过人这个对象可以找到他相关的内容. 一对一单向(主键): 单向一对一主键关联,靠的是它们的主键相等,从Person中能看到IdCard,也就是把t_idCard中的主键拿过来当做t_Pseron的主键. 如图的线表示一个关联,在person中可以看见idcard.即在person中持有idCard的引用 person类的映射关系 <hibernate-mapping> <class name=&qu

Hibernate之映射集合属性

这里先将集合Set在数据库中的存储.就是新建一个表,新建的表的主键对应另一张的外键,而集合的每个值对应一条记录,以同一个set的数据以主键值相同的记录区分. package test.hibernate.set; import java.util.Set; public class User { private Integer id; private String name; private Set<String> addressSet; public Integer getId() { re

【SSH 基础】浅谈Hibernate关系映射(3)

继上篇博客 一对多关联映射(单向) 上面我们介绍了多对一,我们反过来看一对多不就是多对一吗?那还用再进行不同的映射吗?有什么区别吗?一对多和多对一映射原理是一致的,存储是同样的.也就是生成的数据库的表是一样的.他们之间不同的是维护的关系不同. 他们之间不同点是维护的关系不同 *多对一维护的关系是:多指向一的关系.有了此关系,载入多的时候能够将一载入上来. *一对多维护的关系是:一指向多的关系.有了此关系,在载入一的时候能够将多载入上来. 一个班级有多个学生,通过班级能够看到学生信息. Class

浅谈JavaEE中的Hibernate中的四种关系映射(三)

今天我们一起来探讨一下有关Hibernate四种关系映射,大家可能会有疑惑,关系映射不就是只有三种(一对一,一对多,多对多)吗?这里我们再多说一个继承映射关系,虽然它使用频繁度没有前三个那么多,但是它在一些特定情况下,还是非常有用的,至于有什么用下面马上就要讲.这些关系映射实际上就是对应着关系型数据库中的几种关系的类型.我们都知道Hibernate的作用是将面向关系数据操作,转换成面向对象的操作,其中关系映射文件就是实现这个转换的核心.我们都知道如果我们仅仅使用SQL语句建表并且去维护表与表之间

(转)Hibernate框架基础——映射集合属性

http://blog.csdn.net/yerenyuan_pku/article/details/52745486 集合映射 集合属性大致有两种: 单纯的集合属性,如像List.Set或数组等集合属性. Map结构的集合属性,每个属性值都有对应的Key映射. 集合映射的元素大致有如下几种: list:用于映射List集合属性. set:用于映射Set集合属性. map:用于映射Map集合性. array:用于映射数组集合属性. bag:用于映射无序集合. idbag:用于映射无序集合,但为集

hibernate映射集合属性

注意:持久化集合字段必须声明为接口,两个持久化对象不能共享同一个集合元素的引用. 映射集合属性 @ElementCollection{ fetch targetClass } 映射集合属性表 @CollectionTable{ name catalog schema indexes joinColumns uniqueConstraints } @JoinColumn{ columnDefinition name insertable updatable nullable table uniqu

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2pl/ 浅谈 Linux