Hibernate框架学习之三:深入映射文件的配置
2015-12-26 14:42
519 查看
前言
这里主要是对XML版的Hibernate框架的开发进行说明,Annotation版会在另外的文章中在说明。由于Hibernate是一个全方位的ORM框架,那么要实现从Object到Record的完全过渡,实现的桥梁就是这里要讲的映射文件了。映射文件的内容繁多,主要是以开发中会使用到的为主进行说明。大体说来,映射文件主要是对class的映射,还包括属性,属性有分为主键、普通属性与集合属性,甚至还有复合类型等。每种属性都需要进行不同的配置,官方文档看得有点累,所以这里一并做一个总结。
映射文件一览
以上就是映射文件的大体结构,package指定持久化类所在包,class指定具体包下的实体类,name属性指定类的名字(必须与实际的类名一致)。在class内部可以配置主键、普通属性、集合属性和复合类型,以下就对这几种类型的配置进行叙述。
主键
主键就是持久化类中标识属性,用于唯一标识这个对象,在映射文件中需要通过
在日常的开发中,对于主键的使用往往是以逻辑主键为主的,而很少使用物理主键。逻辑主键的意思就是没有任何实际意义的主键,物理主键就是有实际意义的主键。使用逻辑主键的原因在于在进行外键关联的时候能够自动关联,而不需要添加额外的配置;此外,使用物理主键会增加维护的难度(比如在多级关联的时候)。
使用主键必然会涉及到主键生成策略,Hibernate中提供以下几种主键策略:
increment:为int、long和short类型生成唯一标识,但是只能在只有一个进程往数据库表中插入数据的时候才能使用,在集群的情况不要使用
identity:主要是针对类似Mysql等有自增主键的数据库使用
sequence:主要是针对需要使用序列才能使用主键的数据库使用,比如oracle
uuid:使用128位的UUID算法生成字符串类型的唯一标识,这个标识在网络中是唯一的。
hilo:使用高/低位算法高效生成的long、int或者short类型的唯一标识
native:根据底层数据库选择identity、sequence和hilo中的一种
以上主键生成策略是使用比较多的,还有guid、select等策略,感兴趣的可以研究下官方文档。
普通属性
映射普通属性需要使用
type:类型,标识属性名称的类型
column:指定在数据库中列名
not-null:表明是否可以为空,true表示不能为空
formula:该属性可以指定SQL表达式,该属性的值是根据表达生成的,但是在数据库中并没有该column
lazy:表示是否需要延迟加载,默认为false,表示在实例属性被访问的立即被加载
generated:设置该属性映射的数据库列是否由数据库生成,可以选择
以上就是比较常用的属性配置了,下面是对formula属性的一个例子:
下面是News.hbm.xml的配置:
测试程序:
可以在控制台中看到fullcontent是内容title和content属性拼接起来的字符串。有一点的需要注意的是,formula属性sql语句必须使用小括号括起来。其他的普通属性已经在第一篇文章中使用过,这里不再重复。
集合属性
集合属性就包括List、Set、数组和Map四种,下面分别对这四种集合属性的配置进行叙述:
以下的持久化类都以下面的类为模板:
List
在上面Person2类中添加
需要说明的在list标签中需要添加list-index标签,主要是List集合的索引列(从0开始)。
数组
把Person2类中schools属性改成数组类型,修改配置文件如下:
可以看到,使用数组仅仅把标签改成array而已。因为数组本质上也是元素列表。
Set
修改schools类型为Set类型,修改配置文件如下:
在使用Set的时候,并没有list-index标签,而是在element标签中多添加not-null属性,并设置为true。这样做的结果是,Set类型的schools属性将使用person_id和school_name作为联合主键。如果不添加这个属性,那么主键是空的,会抛FieldNotFoundException异常。
Map
添加
有序集合
在有些时候,有序集合也可能需要使用到,首先需要添加
可以看到,与Set(Set是无序无重复的集合)不同的地方在于,多了sort属性,这里使用natural排序策略,表示element的排序使用字母排序的规则进行排序。
组件(复合类型)
比如在Person2类型添加Address2属性,由于Address2也是一个持久化类,所以在数据库中是无法存储的,这里就需要使用组件的配置了。首先需要创建Address2类,如下:
修改配置文件如下:
组件为集合
在Person2类中添加属性
修改配置文件如下:
注意到当组件是集合的时候,需要使用composite-element标签。
以上就是对各种属性类型配置文件的详细配置与叙述,当然使用注解会非常简单,后面还会提到。
这里主要是对XML版的Hibernate框架的开发进行说明,Annotation版会在另外的文章中在说明。由于Hibernate是一个全方位的ORM框架,那么要实现从Object到Record的完全过渡,实现的桥梁就是这里要讲的映射文件了。映射文件的内容繁多,主要是以开发中会使用到的为主进行说明。大体说来,映射文件主要是对class的映射,还包括属性,属性有分为主键、普通属性与集合属性,甚至还有复合类型等。每种属性都需要进行不同的配置,官方文档看得有点累,所以这里一并做一个总结。
映射文件一览
<?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="bean"> <class name="Address"> ... </class> </hibernate-mapping>
以上就是映射文件的大体结构,package指定持久化类所在包,class指定具体包下的实体类,name属性指定类的名字(必须与实际的类名一致)。在class内部可以配置主键、普通属性、集合属性和复合类型,以下就对这几种类型的配置进行叙述。
主键
主键就是持久化类中标识属性,用于唯一标识这个对象,在映射文件中需要通过
<id.../>元素为主键进行设置。在id标签的内部可以使用以下三个常用属性属性:
name、
column和
type。
name属性与持久化类中标识属性的名称是一致的,
column指定在数据库中主键对应的列名。
type属性指定主键的数据类型,这里需要注意的有两点:1,type属性指定的数据类型必须是数据库所支持的数据类型(不过Hibernate已经常用的8中基本数据类型提供类型识别,能够与数据库中的数据类型对上号);2,column属性与type属性都不是必须的,name属性则是必须要指定的。
在日常的开发中,对于主键的使用往往是以逻辑主键为主的,而很少使用物理主键。逻辑主键的意思就是没有任何实际意义的主键,物理主键就是有实际意义的主键。使用逻辑主键的原因在于在进行外键关联的时候能够自动关联,而不需要添加额外的配置;此外,使用物理主键会增加维护的难度(比如在多级关联的时候)。
使用主键必然会涉及到主键生成策略,Hibernate中提供以下几种主键策略:
increment:为int、long和short类型生成唯一标识,但是只能在只有一个进程往数据库表中插入数据的时候才能使用,在集群的情况不要使用
identity:主要是针对类似Mysql等有自增主键的数据库使用
sequence:主要是针对需要使用序列才能使用主键的数据库使用,比如oracle
uuid:使用128位的UUID算法生成字符串类型的唯一标识,这个标识在网络中是唯一的。
hilo:使用高/低位算法高效生成的long、int或者short类型的唯一标识
native:根据底层数据库选择identity、sequence和hilo中的一种
以上主键生成策略是使用比较多的,还有guid、select等策略,感兴趣的可以研究下官方文档。
普通属性
映射普通属性需要使用
<property.../>标签完成。该标签必须制定name属性,标识持久化类的属性名称。除了name属性,还可以配置以下常用属性:
type:类型,标识属性名称的类型
column:指定在数据库中列名
not-null:表明是否可以为空,true表示不能为空
formula:该属性可以指定SQL表达式,该属性的值是根据表达生成的,但是在数据库中并没有该column
lazy:表示是否需要延迟加载,默认为false,表示在实例属性被访问的立即被加载
generated:设置该属性映射的数据库列是否由数据库生成,可以选择
never(表示不由数据库生成)、
always(表示在执行insert和update的时候生成)、
insert(在执行insert操作的时候生成)。
以上就是比较常用的属性配置了,下面是对formula属性的一个例子:
package bean; public class News { private Integer id; private String title; private String content; private String fullcontent; //省略set和get方法 }
下面是News.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="bean"> <!-- 为News类设置一个持久化类 --> <class name="News"> <!-- 设置News的对象标识属性 --> <id name="id"> <!-- 主键生成策略 --> <generator class="native" /> </id> <!-- 普通属性 --> <property name="title" not-null="true"/> <property name="content" not-null="true"/> <property name="fullcontent" column="fullcontent" type="string" formula="(select concat(nt.title,nt.content) from news nt where nt.id=id)"/> </class> </hibernate-mapping>
测试程序:
@Test public void testNews(){ Session session = HibernateUtil.getSessionFactory(1).getCurrentSession(); session.beginTransaction(); // News news = new News(); // news.setTitle("MongoDB教程"); // news.setContent("8天学同MongoDB系列之CRUD操作"); // session.save(news); News n = (News) session.get(News.class, 1); //这里了并没有设置fullcontent的属性,但是仍然调用get方法,看看会输出什么 System.out.println(n.getFullcontent()); session.getTransaction().commit(); }
可以在控制台中看到fullcontent是内容title和content属性拼接起来的字符串。有一点的需要注意的是,formula属性sql语句必须使用小括号括起来。其他的普通属性已经在第一篇文章中使用过,这里不再重复。
集合属性
集合属性就包括List、Set、数组和Map四种,下面分别对这四种集合属性的配置进行叙述:
以下的持久化类都以下面的类为模板:
package bean; public class Person2 { private Integer id; private String name; private Integer age; 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 void setAge(Integer age) { this.age = age; } public Integer getAge() { return age; } }
List
在上面Person2类中添加
List<String> schools属性,并添加set和get方法(后面不再重复)。Person2.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="bean"> <class name="Person2" table="person2"> <id name="id"> <generator class="native" /> </id> <property name="name" type="string"></property> <property name="age" type="integer"></property> </class> <list name="schools" table="school"> <!-- 映射集合属性的外键列 ,这里之所以需要制定notnull属性,是因为在Hibernate中外键列的默认值是false--> <key column="personid" not-null="true"></key> <!-- 映射集合索引列,这里没有指定type属性的原因在于Hibernate直到其属性的值是int类型 --> <list-index column="list_index"></list-index> <!-- 映射需要保存的数据列 --> <element column="school_name" type="string"></element> </list> </hibernate-mapping>
需要说明的在list标签中需要添加list-index标签,主要是List集合的索引列(从0开始)。
数组
把Person2类中schools属性改成数组类型,修改配置文件如下:
<array name="schools" table="school"> <key column="personid" not-null="true"></key> <list-index column="list_index"></list-index> <element column="school_name" type="string"></element> </array>
可以看到,使用数组仅仅把标签改成array而已。因为数组本质上也是元素列表。
Set
修改schools类型为Set类型,修改配置文件如下:
<set name="schools" table="school"> <key column="person_id" not-null="true"></key> <element column="school_name" type="string" not-null="true"></element> </set>
在使用Set的时候,并没有list-index标签,而是在element标签中多添加not-null属性,并设置为true。这样做的结果是,Set类型的schools属性将使用person_id和school_name作为联合主键。如果不添加这个属性,那么主键是空的,会抛FieldNotFoundException异常。
Map
添加
Map<String,Float> scores属性,修改配置文件如下:
<map name="scores" table="score"> <key column="person_id" not-null="true"></key> <map-key column="subject" type="string"></map-key> <element column="grade" type="float" not-null="true"></element> </map>
有序集合
在有些时候,有序集合也可能需要使用到,首先需要添加
SortedSet<String> names属性。修改配置文件如下:
<set name="names" table="name" sort="natural"> <key column="person_id" not-null="true"></key> <element column="nickname" not-null="true" type="string"></element> </set>
可以看到,与Set(Set是无序无重复的集合)不同的地方在于,多了sort属性,这里使用natural排序策略,表示element的排序使用字母排序的规则进行排序。
组件(复合类型)
比如在Person2类型添加Address2属性,由于Address2也是一个持久化类,所以在数据库中是无法存储的,这里就需要使用组件的配置了。首先需要创建Address2类,如下:
package bean; import java.util.Map; public class Address2 { private int id; private String province; private String city; private Person2 owner; //省略set和get方法 }
修改配置文件如下:
<component name="address" class="Address2" unique="true"> <!-- 指定owner属性代表容器实体 --> <parent name="owner"/> <property name="province"></property> <property name="city"></property> <!-- 添加集合属性 --> <map name="power" table="address_power"> <!-- 外键 --> <key column="person_address_id" not-null="true"></key> <!-- 映射map的key --> <map-key column="address_aspect" type="string"></map-key> <!-- 映射map的value --> <element column="address_power" type="integer"></element> </map> </component>
组件为集合
在Person2类中添加属性
Map<String,Address2> adds
修改配置文件如下:
<map name="adds" table="adds_inf"> <!-- 外键 --> <key column="person_id" not-null="true"></key> <!-- key --> <map-key type="string" column="phrase"></map-key> <composite-element class="Address2"> <parent name="owner"/> <property name="province" type="string"></property> <property name="city" type="string"></property> </composite-element> </map>
注意到当组件是集合的时候,需要使用composite-element标签。
以上就是对各种属性类型配置文件的详细配置与叙述,当然使用注解会非常简单,后面还会提到。
相关文章推荐
- Servlet复习(三)监听器
- Failed to find provider info for com.sina.weibo.sdkProvider
- Linux下解决mysql中文乱码问题
- iOS9.0以后那些被不推荐使用(deprecated)方法之:sendAsynchronousRequest was deprecated in iOS 9、UIAlertView was deprecated
- java判断一个char是否是由字母数字组成
- 高斯模糊实现小结
- Mysql中怎样返回一个数据库的所有表名,列名数据类型备注
- Php提交包含特殊字符的参数的方法
- Android App Ant打包
- Cocos2d-x v3.0正式版尝鲜体验【3】 Label文本标签
- 1-5-07:奇数求和
- synchronize和生产者消费者模式
- Oracle undo表空间爆满的解决
- mac查看端口被什么程序占用
- UI - NavigationController
- 没有dig命令的结觉方法
- IE中setTimeout和setInterval不支持回调函数参数的解决方法
- Linux数据恢复
- java MAP 遍历
- 单片机模拟IIC时序读写24C02