Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Hibernate框架学习之注解映射实体类

Hibernate框架学习之注解映射实体类

作者头像
Single
发布于 2018-01-04 10:21:39
发布于 2018-01-04 10:21:39
3.2K00
代码可运行
举报
运行总次数:0
代码可运行

     前面的相关文章中,我们已经介绍了使用XML配置文件映射实体类及其各种类型的属性的相关知识。然而不论是时代的潮流还是臃肿繁杂的配置代码告诉我们,注解配置才是更人性化的设计,于是学习了基本的映射实体类的基本注解,此处做一点总结,后续文章将陆续更新使用注解的方式管理配置各种映射关联关系。本篇主要涉及以下内容:

  • 使用最基本的注解映射一个实体类
  • 使用注解映射属性
  • 使用注解映射主键
  • 其他特殊类型的属性映射

一、使用最基本的注解映射一个实体类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    //省略getter和setter方法
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//在hibernate.cfg.xml中添加实体类
//这样hibernate就会根据配置文件去查找该实体类并做映射操作
<mapping class="User_Annotation.UserInfo"/>

这就是映射一个最简单的实体类所用到的最基本的注解。其中,

  • @Entity:指定当前被修饰的类是一个实体类,用于映射到数据库中的表。
  • @Table(name = "userInfo"):详细指定了该类映射到数据库中的哪张表,这里映射到userInfo表。
  • @Id:指定被修饰的属性将映射到数据表的主键列。
  • @GeneratedValue(strategy = GenerationType.IDENTITY):该注解指定了主键的生成策略,一般不单独出现,这里指定了主键自增的策略。

二、使用注解映射普通属性 对于实体类中属性的映射,一般我们使用@Column进行修饰。该注解有很多属性:

  • name:指定该属性映射到数据表中对应的名称
  • nullable:指定该属性映射的数据表中列是否可以为null,默认为true
  • unique:指定该属性映射到数据表中的列是否具有唯一约束
  • length:指定该属性映射到数据表中的列所能保存数据的最大长度,默认是255

默认情况下,我们不使用@Column修饰属性的时候,hibernate会自动以该属性的名称映射到数据表中的列。

**我们也可以使用注解@Transient修饰属性**,它指明了该属性不会被映射到数据表中某一列,而只是作为一个属性被定义在实体类中。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    @Transient
    private int age;
    //省略getter,setter方法
}

看看hibernate为我们生成的sql语句:

显然,我们age属性并没有被映射到userinfo表中。

对于枚举类型的属性,我们可以使用@Enumerated注解进行修饰。 在某些特殊情况下,有时我们的实体类属性会被定义为枚举类型,那么对于这种数据库中并无法对应的Java类型,该如何映射呢?Hibernate中提供@Enumerated注解来用于我们映射枚举类型,该注解提供一个value属性,该属性可以取两个值:

  • EnumType.STRING:该枚举类型的属性映射到数据表的字段的类型是字符串型
  • EnumType.ORDINAL:该枚举类型的属性映射到数据表的字段的类型是整数类型

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//定义一个枚举类型
public enum Season {
    春季, 夏季, 秋季, 冬季
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;

    @Enumerated(EnumType.STRING)
    private Season season;
    //省略getter,setter方法
}

看看我们的userinfo表:

而当我们@Enumerated(EnumType.ORDINAL)修饰属性的时候,那么Hibernate为我们生成的sql语句是:

这两种情况下,数据表中的season字段一种保存的是枚举类型的具体值,一种保存的是枚举值对应的序号。

**使用@Temporal注解映射日期时间类型** 对于Java来说,表示时间的两个类库,Java.util.Date和java.util.Calendar。而对于数据库而言,表示时间的类型就有很多,例如:date,time,datetime,timestamp等。如何准确的指定最终的映射情况就是我们的@Temporal注解的作用。@Temporal有一个value属性,可以取以下的一些值:

  • TemporalType.DATE:对应于数据库中的date类型
  • TemporalType.TIME:对应于数据库中的time类型
  • TemporalType.TIMESTAMP:对应于数据库中的timestamp类型

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Temporal(TemporalType.DATE)
private Date date;

上述代码指定了Java.util.Date类型属性映射到数据库中的date类型字段。

三、使用注解映射主键属性 最简单的情况下,我们使用注解@Id标识实体类中的某个属性,那么该属性将会被hibernate映射到数据库主键字段,并且无需指定任何属性值。使用使用@GeneratedValue指定主键的生成策略,通过它的strategy属性来指定具体的主键生成方案,该属性可以取如下几个值:

  • GenerationType.AUTO:hibernate默认为该值,它指明了hibernate自动根据底层数据库选择适当的生成策略
  • GenerationType.IDENTITY:适用于MySQL,SQLserver的主键自增长策略
  • GenerationType.SEQUENCE:适用于Oracle的子串策略
  • GenerationType.TABLE:基于辅助表的生成主键策略

如果不是使用Oracle做数据库的话,一般我们会使用IDENTITY作为默认的主键生成策略。

联合主键的映射可以通过多个@Id进行修饰即可,但要求该实体类必须继承 java.io.Serializable并尽可能的重写Object的两个方法,hashCode和equals,因为多个属性唯一确定一条记录,自然需要比较属性的值。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo implements Serializable {
    @Id
    private int id;
    @Id
    private String name;
    //省略getter,setter方法
}

看看hibernate为我们创建的表结构:

四、特殊属性的映射 这里的特殊属性指的是实体类中属性类型非常规的基本类型、包装类型、引用类型,而是类似于集合类型、自定义类型等。我们首先看对于集合类型的属性映射情况。

1、映射集合类型的属性 在hibernate中,所有的集合类型属性都会被单独映射到一张表中,无论是List,Set或者Map都会对应于一张新表。首先我们看List的映射,在详细介绍之前,我们先完整的看看list的映射情况。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;

    @ElementCollection(targetClass = String.class)
    @CollectionTable(name = "address",joinColumns = @JoinColumn(name = "user_id"))
    @OrderColumn(name = "list_id")
    @Column(name = "address")
    private List address;
    //省略getter,setter方法
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//通过实体类实例向数据表中插入数据
UserInfo userInfo = new UserInfo();
userInfo.setName("single");
List<String> list = new ArrayList<String>();
list.add("NanJin");
list.add("XinJiang");
list.add("SiChuan");
list.add("ZheJiang");
list.add("NanTong");
userInfo.setAddress(list);

session.save(userInfo);

看看两张表:

现在,我们再来看看所用到的几个注解。@ElementCollection注解用于修饰一个集合类型的属性,targetClass 指定了该集合类型的对应的泛型类型,我们这里指定了String类型,那么hibernate底层会默认构建一个ArrayList来存放所有的集合元素并且每个元素都限定为String类型。

@CollectionTable注解用于配置为集合属性生成的那张新表的基本信息,name 指定新表的表名,joinColumns的值是一个注解@JoinColumn,该注解专门用于配置外键列,这里我们给他命名为user_id,该字段是address表的值依赖于userinfo表的id主键列的值。

@OrderColumn注解用于配置有序集合的序号,由于list是有序的集合,通过该注解将会在address表中增加一个字段保存各个元素在集合中的序号。

@Column注解则指向我们集合元素所在的列,可以配置他们列名等。

总的来说,一旦hibernate发现实体类中有集合类型的属性需要映射,那么就会为集合属性单独映射出一张表,该表至少有两个字段,一个字段依赖于主表的id字段值,在新表中相同该字段值的记录共同组合成为实体类中的集合属性的值,一个字段保存具体的集合元素的值信息。而对于有序集合来说,还应该包含一个字段用于保存每个集合元素在集合中的序号,该序号字段和第一个外键依赖字段组合成新表的联合主键,唯一标识一条记录。

在hibernate的管理下,当有数据添加进userinfo表的时候,hibernate将拿到该实体类实例的集合属性的值,并连带该实例的id一起插入到新表中。当然,当我们想要获取一个userinfo实例的时候,hibernate也会为我们查询address表,并注入到userinfo实例的集合属性中,默认的注入模式是懒加载。

接着,我们看Set集合的映射情况。Set是一种无序并不重复的集合。具体的配置如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    @ElementCollection(targetClass = String.class)
    @CollectionTable(name = "address",joinColumns = @JoinColumn(name = "user_id",nullable = false))
    @Column(name = "value",nullable = false)
    private Set address;
    //省略getter,setter方法
}

相比List,Set由于是无序的,那么自然是没有索引序列,所以无需配置@OrderColumn,但是它要求所有元素必须不可重复,那么通过制定nullable为false即可。 看看表的生成情况:

对于像set一样的无序集合,新表的主键有user_id和value列联合作为主键,可以保证唯一确定一条数据记录。

最后,我们看看一下Map的映射情况,先看代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    @ElementCollection(targetClass = String.class)
    @MapKeyClass(Integer.class)
    @CollectionTable(name = "address",joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "value")
    private Map map;
    //省略getter,setter方法
}

具体的表生成情况:

对于map这种键值对集合,targetClass 用于指定value值的类型,而@MapKeyClass则用于指定key值的类型,其他的几乎没什么变化,对于map集合映射出来的表,user_id和map的key字段将联合组成此表的主键,唯一确定一条记录。

对于性能的要求,hibernate不推荐实体类属性使用数组类型,建议优先使用集合类型。

2、组件属性映射 所谓的组件类型就是指我们自定义的类类型,在某些情况下,实体类中包含自定类型也是很常见的,那么对于我们自定义的类型该如何来映射到数据表呢?Hibernate的映射策略很简单,对于组件中的每个属性都映射出一个列,也就是相当于把组件给拆解了。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//首先定义一个组件类
@Embeddable
public class Disposition {
    private String mood;
    private String hobby;
    //省略getter,setter方法
}

我们定义了一个类,Disposition并使用@Embeddable注解修改该类。当Hibernate对整个类路径进行扫描的时候,就会注册该类为一个组件类型,那么当我们在实体类中引用该类型的时候,hibernate就能找到相应的组件类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    
    private Disposition disposition;
    //省略getter,setter方法
}

最后生成的数据表结构如下:

组件类的每个属性都被映射到userinfo表中了。当我们通过实体类实例向数据表中插入数据的时候,hibernate会将组件类实例拆分出来的各个属性插入到对应的表字段。当我们通过数据表获取userinfo实例的时候,hibernate判断userinfo中有一个组件类属性,于是创建组件类实例并装载相应的数据表中的数值赋值给userinfo的组件类型属性。

3、集合属性为组件类型的表级映射 集合中的元素除了可以是基本类型,包装类型以外,还可以是组件类型,也就是复合类型。那么对于他们的映射却稍显不同,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//定义一个复合类型
@Embeddable
public class Person {
    private String name;
    private int age;
    private String address;
    //省略getter,setter方法
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "userInfo")
public class UserInfo implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;

    @ElementCollection(targetClass = Person.class)
    @CollectionTable(name = "persons",joinColumns = @JoinColumn(name = "user_id"))
    @OrderColumn(name = "list_index")
    private List list;
    //省略getter,setter方法
}

显然,在实体类中的集合类型属性的映射,大体上是一样的。首先我们通过targetClass 属性指定集合中的元素类型,通过CollectionTable配置为集合生成的新表的基本信息,通过OrderColumn指定索引列。当然,这里我们不需要使用Column注解配置集合元素本身在数据表中的字段名,因为数据库中没有相对应的类型存储。Hibernate选择将集合中的复合类型拆分成多个字段,其他的和普通的集合属性映射并没有太大变化。

只不过对于普通的集合类型映射来说,图中红色框中内容仅仅是一个字段,而对于复合类型,由于数据库中并没有相对应的类型来存储,所以就需要拆分成基本的字段类型。

至此,使用注解方法来配置实体类的基本内容已经简单介绍完了,还有很多相对而言并不常用的基于Hibernate自身的注解并没有做介绍,待作者深入使用后再做相关补充,总结不到之处,望指出!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-11-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Hibernate框架学习之注解配置关系映射
     上篇文章我们通过注解对映射了单个实体类,但是具体项目中往往实体类之间又是相互关联的,本篇文章就是从实体类之间存在的不同关联角度,具体学习下如何映射他们之间的关联,主要涉及内容如下: 单向的一
Single
2018/01/04
2.3K0
Hibernate框架学习之注解配置关系映射
Hibernate学习笔记 多表映射
前面说了Hibernate的单表映射,由于是实体类和数据表之间一对一的映射,所以比较简单。现在就来说说多表映射,这需要涉及到多个实体类和数据表之间的关系。因此稍微复杂一点。
乐百川
2022/05/05
1.6K0
Hibernate基于外键映射的一对一关联关系
基于外键映射的一对一关联关系是Hibernate中常见的关系映射之一。在这种映射中,两个实体类之间存在一个一对一的关系,其中一个实体类作为主实体类,另一个实体类作为从实体类,并且从实体类中包含一个指向主实体类的外键。
堕落飞鸟
2023/05/15
8240
Hibernate双向一对多映射
双向一对多映射是Hibernate中常见的关系映射之一。在这种映射中,两个实体类之间存在一个一对多的关系,其中一个实体类作为“一”的一方,另一个实体类作为“多”的一方。
堕落飞鸟
2023/05/15
9160
JPA实体类中的注解
@Entity   标注于实体类上,通常和@Table是结合使用的,代表是该类是实体类 @Table   标注于实体类上,表示该类映射到数据库中的表,没有指定名称的话就表示与数据库中表名为该类的简单类名的表名相对应,如果是逆向生成表的话就会以简单类名作为表名   如果指定名称,例如@Table(name="tb_user"),就表示映射到数据库中的tb_userz这个表; @Id   标注于属性上,通常是在get方法上,也可以在属性的声明上。   用于表示该属性作为ID主键 @GeneratedValue
二十三年蝉
2018/03/29
3.9K0
Hibernate学习笔记 单表映射
配置好SessionFactory之后,我们就可以开始建立一对一的单表映射了。首先需要建立一个实体类,这里Getter、Setter、toString、equals等方法省略了。我们可以方便的使用IDEA或者Eclipse的生成代码功能轻松生成。
乐百川
2022/05/05
3620
Hibernate注解之基本注解的注解使用
文章目录 1. Hibernate注解之基本注解的注解使用 1.1. 使用注解须知 1.2. 类级别注解 1.3. 属性级别的注解 1.4. 主键相关的注解 1.5. 与非主键相关的注解 1.6. 实例 1.7. @JoinColumn 1.8. @JoinTabl 1.9. 参考文档 Hibernate注解之基本注解的注解使用 使用注解须知 我们在使用注解自动创建表的时候,系统会默认为我们创建一张表Hibernate_sequence,我们可以在Hibernate.cfg.xml文件中添加如下语句解决
爱撒谎的男孩
2019/12/31
2K0
[ SSH框架 ] Hibernate框架学习之四(JPA操作)
一、JPA概述以及它和Hibernate之间的关系 1.1.Hibernate 概述   JPA Java Persistence API,是EJB3规范中负责对象持久化的应用程序编程接口(ORM接口),它定义一系列的注释。这些注释大体可分为:类级别注释、方法级别注释、字段级别注释。给实体类添加适当的注释可以在程序运行时告诉Hibernate如何将一个实体类保存到数据库中以及如何将数据以对象的形式从数据库中读取出来。   目前有两种注释方案可以确定对象与表格之间的对应关系:一种是注释实体类的属性字段(字段级
Kevin_Zhang
2018/05/22
6.8K0
Hibernate 注解配置
近几年来,注解方式的配置因其简单易用的特点深受广大程序员的青睐,Hibernate也添加了对注解配置的支持。接下来我们就以论坛系统为例来讲解基于注解配置实体类和表的映射关系,以及实体和实体的关联关系。
用户9184480
2024/12/19
1040
Hibernate 注解配置
SSH框架之Hibernate第四篇
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
海仔
2019/09/18
3.6K0
Spring data 相关注解
作用是json序列化时将Java bean中的一些属性忽略掉,序列化和反序列化都受影响。
吐吐吐吐吐葡萄皮
2019/04/04
2.1K0
Spring data 相关注解
【Hibernate】Hibernate框架配置详解
通过Hibernate我们可以方便地操作数据库读取出来的信息,减少了繁琐的JDBC操作。
陈树义
2022/04/29
1.4K0
探索Hibernate的奥秘:简解其使用与实现过程
在现代的Java开发中,数据持久化是一个至关重要的环节。而在众多持久化框架中,Hibernate以其强大的功能和灵活性,成为了开发者们的首选工具。本文将详细介绍Hibernate的原理、实现过程以及其使用方法,希望能为广大开发者提供一些有价值的参考。
繁依Fanyi
2024/06/23
3320
Spring Data JPA 就是这么简单
jpa 的全称是 Java Persistence API , 中文的字面意思就是 java 的持久层 API , jpa 就是定义了一系列标准,让实体类和数据库中的表建立一个对应的关系,当我们在使用 java 操作实体类的时候能达到操作数据库中表的效果(不用写sql ,就可以达到效果),jpa 的实现思想即是 ORM (Object Relation Mapping),对象关系映射,用于在关系型数据库和业务实体对象之间作一个映射。
程序员小猿
2021/01/19
7K0
Spring Data JPA 就是这么简单
Java 数据库存储数组的方法
在现代软件开发中,数组是常用的数据结构之一。然而,在关系数据库中直接存储数组并不是一个简单的任务。关系数据库通常擅长存储简单的数据类型如整数、字符串和日期等,但对于复杂的数据类型如数组、列表或对象,通常需要采用特殊的方法进行处理。本文将详细介绍几种在Java中将数组存储到数据库的方法,包括使用JPA、JSON、XML、以及关系型数据库的数组类型等。
繁依Fanyi
2024/07/30
2810
【Java】已解决:org.hibernate.TypeMismatchException
已解决:org.hibernate.TypeMismatchException
屿小夏
2024/09/15
1370
【Java】已解决:org.hibernate.TypeMismatchException
Java 数据库存储数组的方法
在现代软件开发中,数组是常用的数据结构之一。然而,在关系数据库中直接存储数组并不是一个简单的任务。关系数据库通常擅长存储简单的数据类型如整数、字符串和日期等,但对于复杂的数据类型如数组、列表或对象,通常需要采用特殊的方法进行处理。本文将详细介绍几种在Java中将数组存储到数据库的方法,包括使用JPA、JSON、XML、以及关系型数据库的数组类型等。
繁依Fanyi
2024/09/20
1510
理解JPA注解@GeneratedValue
通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法, JPA提供四种标准用法,由@GeneratedValue的源代码可以明显看出.
JavaEdge
2018/08/02
3.3K0
Spring Data JPA 时间注解:@CreatedDate 和 @LastModifiedDate
选择 Spring Data JPA 框架开发时,常用在实体和字段上的注解有@Entity、@Id、@Column等。在表设计规范中,通常建议保留的有两个字段,一个是更新时间,一个是创建时间。Spring Data JPA 提供了相应的时间注解,只需要两步配置,就可以帮助开发者快速实现这方面的功能。
happyJared
2020/02/11
4.4K1
Java一分钟之-JPA实体关系:一对一, 一对多, 多对多
Java Persistence API (JPA) 是Java平台上的一个对象关系映射 (ORM) 规范,用于简化数据库操作,其中实体关系的映射是核心内容之一。本文将深入浅出地探讨JPA中的三种基本实体关系类型:一对一、一对多、多对多,揭示常见问题、易错点及其避免策略,并附上简洁的代码示例。
Jimaks
2024/06/14
3860
相关推荐
Hibernate框架学习之注解配置关系映射
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验