(转)Hibernate框架基础——映射普通属性
http://blog.csdn.net/yerenyuan_pku/article/details/52739871
持久化对象与OID
对持久化对象的要求
- 提供一个无参的构造器。使Hibernate可以使用Constructor.newInstance()来实例化持久化类。
- 提供一个标识属性(identifier property)。通常映射为数据库表的主键字段。如果没有该属性,一些功能将不起作用,如:Session.saveOrUpdate()。
- 为类的持久化字段声明访问方法(get/set)。Hibernate对JavaBean风格的属性实行持久化。
- 使用非final类。在运行时生成代理是Hibernate的一个重要的功能。如果持久化类没有实现任何接口,Hibnernate使用CGLIB生成代理。如果使用的是final类,则无法生成CGLIB代理。
- 重写eqauls()和hashCode()方法。如果需要把持久化类的实例放到Set中(当需要进行关联映射时),则应该重写这两个方法。
例,我们可在cn.itcast.c_hbm_property包下创建这样一个持久化类——User.java。
/**
* 实体
*/
public class User {
private int id;
private String name;
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;
}
@Override
public String toString() {
return "[User: id=" + id + ", name=" + name + "]";
}
}
OID
为了在系统中能够找到所需对象,需要为每一个对象分配一个唯一的标识号。在关系数据库中称之为主键,而在对象术语中,则叫做对象标识(Object identifier-OID)。
对象/关系数据库映射文件(hbm.xml)
Hibernate采用XML格式的文件来指定对象和关系数据之间的映射。在运行时Hibernate将根据这个映射文件来生成各种SQL语句。映射文件的扩展名为”.hbm.xml”。
映射文件示例: 
持久化类的属性及属性映射(普通属性)
对应于cn.itcast.c_hbm_property包下的持久化类——User.java,我们应在该包下创建出对象/关系数据库映射文件——User.hbm.xml。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.c_hbm_property">
<!--
name属性:哪个类
table属性:对应哪个表,如果不写,默认的表名就是类的简单名称
-->
<class name="User" table="t_user">
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="name" type="string" column="name" length="20" not-null="true" />
</class>
</hibernate-mapping>
映射配置:
<property name="name" type="string" column="name" length="20" not-null="true" />
即为映射的普通属性,普通属性指数据库中的基本类型,如字符串、日期、数字等。下面我们就来详解<property ... />元素中的各个属性:
- name属性:对象中的属性名,必须要有。
- type属性:类型,如果不写,Hibernate会自动检测。可以写java中类的全名或是写hibernate类型。
- column属性:对应表中的列名,如果没写,默认为属性名。
- length属性:长度,不是所有的类型都有长度属性,比如varchar有,但int没有,如果不写默认为255。
- not-null属性:非空约束,默认为false。
所以上面的映射配置,直接写成这样干巴巴的配置:
<property name="name" />
也是可以的。
单单是编写上面这样一个映射文件——User.hbm.xml,涉及到的知识点还是蛮多的,下面我们一一讲解。
Hibernate的映射类型
内置映射类型
| Hibernate | java | sql | 取值范围 |
|---|---|---|---|
| integer/int | java.lang.Integer/int | INTEGER | 4 |
| long | java.lang.Long/long | BIGINT | 8 |
| short | java.lang.Short/short | SMALLINT | 2 |
| byte | java.lang.Byte/byte | TINYINT | 1 |
| float | java.lang.Float/float | FLOAT | 4 |
| double | java.lang.Double/double | DOUBLE | 8 |
| big_decimal | java.math.BigDecinimal | NUMERIC | 8位含2位小数部分 |
| character | char/java.lang.Character/java.lang.String | CHAR(1) | 定长字符 |
| string | java.lang.String | VARCHAR | 变长串 |
| boolean | boolean/java.lang.Boolean | BIT | 布尔 |
| yes_no | boolean/java.lang.Boolean | CHAR(1) | 布尔 |
| true_fasle | boolean/java.lang.Boolean | CHAR(1) | 布尔 |
java时间和日期类性
| Hibernate | java | sql | 取值范围 |
|---|---|---|---|
| date | java.util.Date/java.sql.Date | DATE | YYYY-MM-DD |
| time | java.util.Date/java.sql.Time | TIME | HH:MM:SS |
| timestamp | java.util.Date/java.sql.timestamp | TIMESTAMP | YYYYMMDDHHMMSS |
| calendar | java.util.Calendar | TIMESTAMP | YYYYMMDDHHMMSS |
| calendar_date | java.util.Calendar | DATE | YYYY-MM-DD |
大对象类型的映射
| Hibernate | java | sql |
|---|---|---|
| binary | byte[] | VARBINARY(BLOB) |
| text | String | CLOB |
| serializable | 实现类 | BARBINARY(BLOB) |
| clob | java.sql.Clob | CLOB |
| blob | java.sql.Blob | BLOB |
JDK自带的个别java类的映射类型
| Hibernate | java | sql |
|---|---|---|
| class | java.lang.Class | VARCHAR |
| locale | java.util.Locale | VARCHAR |
| timezone | java.util.TimeZone | VARCHAR |
| currency | java.util.Currency | VARCHAR |
设置类的包名
如果在一个映射文件中包含多个类,并且这些类位于同一个包中,可以设置<hibernate-mapping>元素的package属性,以避免为每个类提供完整的类名。
指定类的全限定名:
在<hibernate-mapping>元素中指定package属性,就只需指定简单类名了: 
处理sql引用表示符
在实际开发中,我们要编写的持久化类不会这么简单,也就是说User类不会只有
private int id;
private String name;
这两个字段。通常它含有的字段挺多的,例如:
/**
* 实体
*/
public class User {
private int id;
private String name;
private Integer age;
private Date birthday; // 生日
private String desc; // 一大段说明
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "[User: id=" + id + ", name=" + name + "]";
}
}
我们接下来就要修改映射文件——User.hbm.xml了。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.c_hbm_property">
<!--
name属性:哪个类
table属性:对应哪个表,如果不写,默认的表名就是类的简单名称
-->
<class name="User" table="t_user">
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="name" type="string" column="name" length="20" not-null="true" />
<property name="age" type="int" column="age_" />
<property name="birthday" type="date" column="birthday_" />
<!-- 指定使用text类型时,最好再指定length,以确定生成的SQL类型是能够存放指定数量的字符的。 -->
<property name="desc" type="text" length="5000" column="`desc`"/>
</class>
</hibernate-mapping>
我们从中可以看到User持久化类的属性desc的映射配置为:
<property name="desc" type="text" length="5000" column="`desc`"/>
思考一个问题:column属性为何要写成column=”`desc`”?可参考下面这段话:
在SQL语法中,表示符是指用于数据库表、视图、字段或索引等名字的字符串,常规表示符不包括空格,也不包含特殊字符,因此无需使用引用符号。如果数据库表名或列名包含特殊字符,可以使用引用表示符(键盘~下面的字符)。
用更通俗易懂的话说就是:当列名与关键字冲突时,可以通过column属性指定一个其他的列名,或是使用反引号包围起来(不建议使用)。
现在我们编写单元测试来进行测试,在cn.itcast.c_hbm_property包下编写一个单元测试类——App.java。
public class App {
private static SessionFactory sessionFactory;
static {
sessionFactory = new Configuration() //
.configure() // 读取配置文件
.addClass(User.class) //
.buildSessionFactory();
}
@Test
public void testSave() throws Exception {
// 创建对象实例
User user = new User();
user.setName("张三");
user.setAge(20);
user.setBirthday(new Date());
user.setDesc("一大段的说明,此处省略5000字...");
// 保存
Session session = sessionFactory.openSession(); // 打开一个新的Session
Transaction tx = session.beginTransaction(); // 开启事务
session.save(user);
tx.commit(); // 提交事务
session.close(); // 关闭Session,释放资源
}
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
User user = (User) session.get(User.class, 1); // 获取?
System.out.println(user.getId());
System.out.println(user.getName());
System.out.println(user.getDesc());
tx.commit();
session.close();
}
}
运行testSave()方法,再去查看t_user表结构:
发现t_user表desc列的数据类型是longtext,而若是一定要让desc列的数据类型是text,也是有法子的,可以将
<property name="desc" type="text" length="5000" column="`desc`"/>
修改为:
<property name="desc">
<column name="desc_" length="5000" sql-type="text"></column>
</property>
这时再次运行testSave()方法,再去查看t_user表结构:
发现t_user表desc列的数据类型是text了,我们的目的达到了。虽说可以这样写,但是一般不建议这样写。
最后,我们在持久化类——User.java中加入一个字段:
private byte[] photo; // 头像图片(二进制内容)
映射文件中增加:
<!-- 头像,二进制类型,最好指定长度 -->
<property name="photo" type="binary" length="102400"></property>
这时我们修改单元测试类——App.java的代码为:
public class App {
private static SessionFactory sessionFactory;
static {
sessionFactory = new Configuration() //
.configure() // 读取配置文件
.addClass(User.class) //
.buildSessionFactory();
}
@Test
public void testSave() throws Exception {
// 读取图片文件
InputStream in = new FileInputStream("c:/1.jpg");
byte[] photo = new byte[in.available()];
in.read(photo);
in.close();
// 创建对象实例
User user = new User();
user.setName("张三");
user.setAge(20);
user.setBirthday(new Date());
user.setDesc("一大段的说明,此处省略5000字...");
user.setPhoto(photo);
// 保存
Session session = sessionFactory.openSession(); // 打开一个新的Session
Transaction tx = session.beginTransaction(); // 开启事务
session.save(user);
tx.commit(); // 提交事务
session.close(); // 关闭Session,释放资源
}
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
User user = (User) session.get(User.class, 1); // 获取?
System.out.println(user.getId());
System.out.println(user.getName());
System.out.println(user.getDesc());
System.out.println(user.getPhoto());
OutputStream out = new FileOutputStream("c:/copy.png");
out.write(user.getPhoto());
out.close();
tx.commit();
session.close();
}
}
测试,通过,大发!!!
(转)Hibernate框架基础——映射普通属性的更多相关文章
- (转)Hibernate框架基础——映射集合属性
http://blog.csdn.net/yerenyuan_pku/article/details/52745486 集合映射 集合属性大致有两种: 单纯的集合属性,如像List.Set或数组等集合 ...
- (转)Hibernate框架基础——映射主键属性
http://blog.csdn.net/yerenyuan_pku/article/details/52740744 本文我们学习映射文件中的主键属性,废话不多说,直接开干. 我们首先在cn.itc ...
- (转)Hibernate框架基础——一对多关联关系映射
http://blog.csdn.net/yerenyuan_pku/article/details/52746413 上一篇文章Hibernate框架基础——映射集合属性详细讲解的是值类型的集合(即 ...
- Hibernate框架基础
Hibernate框架基础 Hibernate框架 ORM概念 O, Object 对象 R, Realtion 关系 (关系型数据库: MySQL, Oracle…) M,Mapping 映射 OR ...
- (转)Hibernate框架基础——Java对象持久化概述
http://blog.csdn.net/yerenyuan_pku/article/details/52732990 Java对象持久化概述 应用程序的分层体系结构 基于B/S的典型三层架构 说明 ...
- (转)Hibernate框架基础——多对多关联关系映射
http://blog.csdn.net/yerenyuan_pku/article/details/52756536 多对多关联关系映射 多对多的实体关系模型也是很常见的,比如学生和课程的关系.一个 ...
- (转)Hibernate框架基础——cascade属性
http://blog.csdn.net/yerenyuan_pku/article/details/52760010 我们以部门和员工的关系为例讲解一对多关联关系映射时,删除部门时,如果部门有关联的 ...
- 详谈Hibernate框架关系映射!
接触Hibernate也有一小段的时间了,愈发的觉得Hibernate是个神奇的东西,为什么这么说呢?因为你可以不懂一行sql,直接面向对象,就可以将数据直接保存到数据库去!! 你还可以保存一个对象, ...
- Hibernate框架--关联映射,一对多,多对多 inverse cascade
回顾Hibernate: 1. hibernate开发环境搭建 ----> 引入jar: hibernate.jar + required + jpa + 驱动包 ---> hiberna ...
随机推荐
- 我是怎样自学 Android 的?
1. Java知识储备 本知识点不做重点解说: 对于有基础的同学推荐看<Java编程思想>,巩固基础,查漏补全,了解并熟悉很多其它细节知识点. 对于没有基础的同学推荐看一本Java基础的书 ...
- Java内存问题的一些见解
在Java中,内存泄露和其它内存相关问题在性能和可扩展性方面表现的最为突出.我们有充分的理由去具体地讨论他们. Java内存模型--或者更确切的说垃圾回收器--已经攻克了很多内存问题. 然而同一时候, ...
- web 开发之js---js 中的数组操作
js数组元素的添加和删除一直比较迷惑,今天终于找到详细说明的资料了,先给个我测试的代码^-^var arr = new Array();arr[0] = "aaa";arr[1] ...
- POJ 1625 Censored! (AC自己主动机 + 高精度 + DP)
题目链接:Censored! 解析:AC自己主动机 + 高精度 + 简单DP. 字符有可能会超过128.用map映射一下就可以. 中间的数太大.得上高精度. 用矩阵高速幂会超时,简单的DP就能解决时间 ...
- 操作系统学习笔记:CPU调度
CPU调度的目的在于提高CPU利用率,不让CPU闲着.CPU是宝贵的资源,如果有一个进程,本来在CPU中运行,忽然因为要使用IO资源,于是转而请求IO,这边CPU挂起,造成就绪队列中的其他进程等待,这 ...
- USACO Section 1.2PROB Miking Cows
贪心做过去,先对每个时间的左边点进行排序,然后乱搞,当然线段树也可以做 /* ID: jusonal1 PROG: milk2 LANG: C++ */ #include <iostream&g ...
- Maven 项目管理 —— 安装与配置
Maven 是一种全新的项目构建方式,基于项目对象模型(POM,Project Object Model)的思想,Maven 可以管理项目的整个生命周期,包括编译.构建(build).测试.发布以及报 ...
- Java 系统工具类 —— System、Scanner、Runtime
0. 静态成员变量 System.out:是 PrinterStream 型变量: public final class System { ... public final static InputS ...
- JeePlus:Maven 安装配置
ylbtech-JeePlus:Maven 安装配置 1.返回顶部 1. Maven 安装配置 1 Maven 由于Maven依赖Java运行环境,因此使用Maven之前需要配置Java的运行环境.下 ...
- 02_cfork分叉进程
fork函数.调用它就可以在当前的进程当中给它分叉出一个新的进程.分叉出的进程就可以看看它有什么特点?