【hibernate】<第二节>hibernate的一对多映射(基本类型)
所需工具与前文一致!
第一部分内容:基本类型的一对多(one to many)
以部门表与员工表为例:
目录结构:
hibernate.cfg.xml内容
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <!-- 基础配置(必须的配置) --> 8 <!-- 配置数据库的驱动类 --> 9 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 10 <!-- 配置数据库的别名 --> 11 <!-- 什么是别名?大家都知道hibernate一个重要的优点是可以跨数据库使用,实现这点的原因就在这里,hibernate为每种常见的数据库都 12 实现了特定的sql语句,比如就分页来说,mysql就是limit语句,而oracle就是恶心的多个select嵌套在一起,但是hibernate本身不 13 能识别数据库的类型,在这里我们通过设置别名来告诉hibernate使用什么数据库的语句来实现 14 不同数据库的别名分别是什么? 15 hibernate的包里有一个是常用配置文件,从这里可以查到 16 Hiberante开发包__hibernate-distribution-3.6.0.Final-dist\hibernate-distribution-3.6.0.Final\project\etc\hibernate.properties 17 --> 18 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 19 <!-- 配置数据库的url地址 --> 20 <property name="hibernate.connection.url">jdbc:mysql:///test</property> 21 <!-- 配置数据库的用户名 --> 22 <property name="hibernate.connection.username">root</property> 23 <!-- 配置数据库的密码 --> 24 <property name="hibernate.connection.password">root</property> 25 26 <!-- 非必须配置 --> 27 <!-- 是否在控制台打印sql语句,建议开发时打开,发布后关闭 --> 28 <property name="show_sql">true</property> 29 <!-- 格式化控制台打印的sql语句 --> 30 <!--<property name="format_sql">true</property> --> 31 <!-- hibernate有两种开发流程,一个是先在数据库里建好库,建好表,再写对应的实体类,与对应关系。另一种是按需求直接写实体类与对应关系,再通过hibernate自动 32 生成对应的数据库里的表。如果想自动生成表就要配置这个hbm2ddl.auto这个属性了,这个属性有好几个值,一般用update,其余的查文档吧 33 --> 34 <property name="hbm2ddl.auto">update</property> 35 36 <!-- 添加映射文件 --> 37 <!-- <mapping resource="cn/kiwifly/entity/User.hbm.xml"/> --> 38 </session-factory> 39 </hibernate-configuration>
两个实体类:
Department.java
package cn.kiwifly.entity; import java.util.HashSet; import java.util.Set; public class Department { private Integer id; private String name; private Set<Employee> employees = new HashSet<>(); 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 Set<Employee> getEmployees() { return employees; } public void setEmployees(Set<Employee> employees) { this.employees = employees; } public String toString() { return "Department [id=" + id + ", name=" + name + ", employees=" + employees + "]"; } }
Employee.java
package cn.kiwifly.entity; public class Employee { private Integer id; private String name; private Integer age; private Department department; public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String toString() { return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", department=" + department.getName() + "]"; } }
两个实体类的配置文件:
department.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.kiwifly.entity"> <class name="Department" table="t_department"> <id name="id" column="id" type="integer"> <generator class="native" /> </id> <property name="name" column="name" type="string"/> <set name="employees" table="t_employee" inverse="true"> <key column="department_id" /> <one-to-many class="Employee" /> </set> </class> </hibernate-mapping>
employee.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.kiwifly.entity"> <class name="Employee" table="t_employee"> <id name="id" column="id" type="integer"> <generator class="native" /> </id> <property name="name" column="name" type="string" /> <property name="age" column="age" type="integer" /> <many-to-one name="department" column="department_id" class="Department" /> </class> </hibernate-mapping>
hibernate 一对多映射格式
类型 |
特点 |
映射格式 |
Set |
无序,不重复 |
<set name=”主表中一对多的属性“ table=”集合表”> <key column=”集合表外键” /> <element type=”字段类型” column=”字段名”> </set> |
List |
有序,可重复 |
<list name=”主表中一对多的属性“ table=”集合表”> <key column=”集合表外键” /> <list-index column=”排序序列”/> <element type=”字段类型” column=”字段名”> </list> |
Array |
有序,可重复(同List) (因不能动态增长,所以不常用) |
<array name=”主表中一对多的属性“ table=”集合表”> <key column=”集合表外键” /> <list-index column=”排序序列”/> <element type=”字段类型” column=”字段名”> </array> (与List基本一样) |
Bag |
有序,可重复 (hibernate特有对象) |
<bag name=”主表中一对多的属性“ table=”集合表”> <key column=”集合表外键” /> <element type=”字段类型” column=”字段名”> </bag> (与Set基本一样) |
Map |
键值对,无序,Key不可重复 |
<map name=”主表中一对多的属性“ table=”集合表”> <key column=”集合表外键” /> <map-key type=”类型” column=”键字段”></map-key> <element type=”字段类型” column=”字段名”> </map> |
一些细节问题:
1、写类的toStirng()方法的时候要注意,如果只是有eclipse的快捷键复写,可能会出现栈溢出的异常,因为eclipse的复写只是写了类名,因为这里的相互引用会出现死循环
2、以上重点在set的映射,其余的都是在其基础上映射的
3、List与Array与Set相比多了一个list-index属性,就是这个属性来让list变的有序,这么就引出一个问题;数据库如何保证数据的有序性哪?
hibernate的作法:设置一个索引字段;用以保存顺序;
4、set有两个重要的属性inverse与cascade这里没说,但很重要,有很多博客说的很详细,可以看看