Hibernate学习之映射文件

pojo映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

<class name="com.mamh.hibernate.demo.entities.News" table="hb_news" schema="mage" select-before-update="true">
<id name="id">
<column name="hb_id" sql-type="int(11)"/>
<!--指定主键的生成方法,native使用数据库本地方式,mysql就是自动增长的数字-->
<generator class="native"/>
</id>
<property name="title">
<column name="hb_title" sql-type="varchar(1024)" length="1024" not-null="true"/>
</property>
<property name="author">
<column name="hb_author" sql-type="varchar(2048)" length="2048" not-null="true"/>
</property>
<property name="date">
<column name="hb_date" sql-type="datetime" not-null="true"/>
</property>
</class>
</hibernate-mapping>

hibernate-mapping节点 中的package属性

1
2
<hibernate-mapping package="com.mamh.hibernate.demo.entities">

这个指定了,在class节点中的name属性就不用写全类名了。


class节点,class节点在hibernate-mapping下面。
一个hibernate-mapping可以写多个class节点,不过一般都是一个。一个class一个xml文件。

1
<class  name="News" table="hb_news" schema="mage" select-before-update="true">
  • name 全类名
  • table 数据库中的对应的表名
  • dynamic-insert 这个和动态更新类似
  • dynamic-update动态更新
  • select-before-update=”true”,设置hibernate在更新某个持久化对象之前是否需要先执行一次查询,默认是false。建议设置false。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    @Test
public void testDynamicUpdate(){
News news = (News) session.get(News.class, 1);
news.setAuthor("xxxxxxxxxxxxxxxx");
}
如果class下不设置dynamic-update动态更新为true,上面的更新操作会执行如下的sql语句
Hibernate:
update
mage.hb_news
set
hb_title=?,
hb_author=?,
hb_date=?
where
hb_id=?
这个sql语句会更新其他的不相关的属性。
如果class 设置dynamic-update动态更新为true,只会更新设置的那一个属性
@Test
public void testDynamicUpdate(){
News news = (News) session.get(News.class, 1);
news.setAuthor("dfsdfasdf");
}
输出如下:
Hibernate:
update
mage.hb_news
set
hb_author=?
where
hb_id=?



id节点,id节点在class节点里面

1
2
3
4
5
6
7
<id name="id">
<column name="hb_id" sql-type="int(11)"/>
<!--指定主键的生成方法,native使用数据库本地方式,mysql就是自动增长的数字-->
<generator class="native"/>
</id>


hibernate使用对象标示符(OID)来建立内存中的对象和数据库表中记录的对应关系,对象的OID和数据表的主键对应。
hibernate通过标识符生成器来为主键赋值。

hibernate推荐数据表中使用代理主键(即不具备业务含义的字段,代理主键通常为整型,因为整型比字符串节省数据库空间)。

其中id元素用来设置对象标识符,generator子元素用来设定标识符生成器。

hibernate提供了标识符生成器接口,IdentifierGenerator,并提供了各种内置实现。

id节点中的 generator子节点

  • increment属性,由hibernate以递增方式为代理主键赋值。测试可以使用,正式开发不能用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        @Test
    public void testIdGenerator() {
    News news = new News("ff", "fff", new Date(new java.util.Date().getTime()));
    session.save(news);

    }
    Hibernate:
    select
    max(hb_id)
    from
    hb_news
    =destroy=
    Hibernate:
    insert
    into
    mage.hb_news
    (hb_title, hb_author, hb_date, hb_id)
    values
    (?, ?, ?, ?)
  • identity,由底层数据库来负责生成。mysql可以使用这个。

  • sequence,利用底层数据库提供的序列来生成主键。DB2,oracle支持。

  • hilo,有hibernate安装一种high/low算法生成主键,这种方式不依赖任何数据库。都支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Hibernate: 
select
next_hi
from
hibernate_unique_key for update

Hibernate:
update
hibernate_unique_key
set
next_hi = ?
where
next_hi = ?
=destroy=
Hibernate:
insert
into
mage.hb_news
(hb_title, hb_author, hb_date, hb_id)
values
(?, ?, ?, ?)

Process finished with exit code 0
  • native,依据数据库对自动生成主键的支持方式自动选择

property节点,在class节点下面

1
2
3
4
5
6
7
8
9
<property name="title">
<column name="hb_title" sql-type="varchar(1024)" length="1024" not-null="true"/>
</property>
<property name="author">
<column name="hb_author" sql-type="varchar(2048)" length="2048" not-null="true"/>
</property>
<property name="date">
<column name="hb_date" sql-type="datetime" not-null="true"/>
</property>

映射派生属性

1
2
3
<!-- 映射派生属性 -->
<property name="desc" formula="(select concat(hb_author, ':= ', hb_title) from hb_news)"/>

java中时间日期的映射

java中代表时间日期的类型包括java.util.Date 和 java.util.Calendar
此外,jdbc api提供了3个扩展 java.util.Date 的子类java.sql.Date,java.sql.Time,
java.sql.Timestamp,这个3个类分别和标准的sql类型的date,time,timestamp类型对应。

在标准sql中,DATE表示日期,TIME表示时间,TIMESTAMP表示时间戳,同时包含日期和时间。

java.util.Date 可以对应3中类型,设计类的时候建议使用这个类型。

如何把 java.util.Date 映射为DATE,TIME ,TIMESTAMP类型呢?可以通过property的type属性。

1
2
3
<property name="date" type="timestamp">
<column name="hb_date" />
</property>

映射大数据类型

1
2
3
4
5
6
7
8

<property name="content" type="clob">
<column name="hb_content" sql-type="mediumtext"/>
</property>

<property name="image" type="blob">
<column name="hb_image" sql-type="mediumblob"/>
</property>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
public void testBlob() {
News news = new News();
news.setTitle("title");
news.setAuthor("author");
news.setDate(new java.util.Date());

news.setDesc("desc.......");

InputStream stream = null;
try {
stream = new FileInputStream("/home/mamh/马哥私房菜-8X8-02.jpg");
Blob image = Hibernate.getLobCreator(session).createBlob(stream, stream.available());
news.setImage(image);
} catch (IOException e) {
e.printStackTrace();
}

session.save(news);
}

组件映射

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void testWorker() {
Worker worker = new Worker();
Pay pay = new Pay();
pay.setMonthlyPay(12000);
pay.setYearPay(170000);
pay.setVacation(10);

worker.setName("bright.ma");
worker.setPay(pay);

session.save(worker);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<class name="Worker" table="hb_work" schema="mage" select-before-update="true" dynamic-update="true">
<id name="id">
<column name="hb_id" sql-type="int(11)"/>
<!--指定主键的生成方法,native使用数据库本地方式,mysql就是自动增长的数字-->
<generator class="hilo"/>
</id>
<property name="name" type="string" update="true" index="hb_title">
<column name="hb_name" length="1024" not-null="true" unique="true"/>
</property>


<component name="pay">
<property name="monthlyPay" column="hb_monthly_pay"/>
<property name="yearPay" column="hb_year_pay"/>
<property name="vacation" column="hb_vacation"/>
</component>


</class>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Worker {
private Integer id;
private String name;

private Pay pay;
worker类里面有个其他类pay。

public class Pay {
private int monthlyPay;
private int yearPay;
private int vacation;