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

来源:互联网 发布:万惠事件知乎 编辑:程序博客网 时间:2024/06/15 22:23

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

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

主键:主键是指标识某个表中唯一且非空的一条记录行的列,这个列中的值不允许有重复的值,用于确定一个表中的一条记录,实

    际上主键就是告诉别人:这个数据列是唯一的。

外键:引用另外一个表中的主键,在当前表中不一定为唯一的,但是在被引用表中一般唯一。对于关系型数据库来说(比如MySQL)

    外键是联系数据表之间的唯一方式,主要目的是控制存储在外键表中的数据。

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

例如:

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

下面开始映射集合属性:

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


Hibernate映射List集合


1:PersonList.java

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

package com.mao;import java.util.ArrayList;import java.util.Date;import java.util.List;import javax.persistence.*;@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",joinColumns=@JoinColumn (name="person_id",nullable=false))//指定保存集合元素的列为:school_name@Column (name="school_name")//映射集合元素的索引的列@OrderColumn(name="list_order")private List<String> school=new ArrayList<>();//省略相应的set、get方法}

2:主程序 PersonManagerList.java

package com.mao;import java.io.File;import java.io.FileInputStream;import java.util.Date;import org.hibernate.*;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并存入字节数组contentnew FileInputStream(file).read(content);person.setPic(content);person.setBirth(new Date());person.getSchool().add("菜鸟学院");//保存信息并将对象持久化sess.save(person);//提交事务tx.commit();sess.close();sf.close();}}

3:配置文件 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><span style="font-size:14px;"></span>

4:运行结果


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



这样person_id是表一的主键 ,然后表二把表一的主键作为外键,这样两个表就通过person_id联系起来了。

5:映射集合常用的注解

 @ElementCollection:用于映射集合属性

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

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

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


Hibernate映射Array集合


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

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

2:PersonManagerArray.java

 PersonArray person=new PersonArray();person.setName("VipMao");File file=new File("image/2.jpg");byte[]content=new byte[(int) file.length()];//创建读取数据流来读取图片对象file并存入字节数组contentnew 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);

3:运行结果




Hibernate映射Set集合

 

1:PersonSet.java

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

2:PersonManagerSet.java

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

3:运行结果



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


Hibernate映射Map集合


1:PersonMap.java

@ElementCollection(targetClass=Float.class)@CollectionTable(name="score_inf",joinColumns=@JoinColumn(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<>();

2: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);

3:运行结果



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

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

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

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


1 0
原创粉丝点击