前言

上一节我们讲解了Hibernate的主键生成策略,本节我们继续来讲讲Hibernate中针对列的映射即@Column注解,文中若有错误之处,还望指正。

@Column注解详解

我们看到如上针对列注解上所对应的属性设置,主要有列名、唯一约束(默认为非)、可空(默认为空)、可插入(默认为true)、可更新(默认为true)、列定义(默认空字符串)、所属表名(默认为空字符串)、长度(默认为255)、小数位数(默认为0)等,这里我们重点讲解insertable、updatable、columnDefinition、precision属性。

属性insertable和updatable

首先我们给出如下两个POJO对象,一个是国家、另外一个则是城市邮编,一个国家下有多个城市即对应多个邮编,而一个城市邮编则只属于特定国家,所以国家和城市邮编是一对多的关系,后续讲解关系映射时会进一步详细讲解,如下:@Entity

@Entity
public class Country { public Country() {
} //国家编码
@Id
@Column(length = 20)
private String iso_code; //国家名称
@Column
private String name; public void setIso_code(String iso_code) {
this.iso_code = iso_code;
} public String getIso_code() {
return iso_code;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @OneToMany(mappedBy = "country", cascade = CascadeType.ALL)
private List<Zip> zips; public List<Zip> getZips() {
return zips;
} public void setZips(List<Zip> zips) {
this.zips = zips;
}
}

在上述国家对象中,我们以iso_code作为主键且值由我们显式指定,在如下城市邮编对象中,我们显式指定外键列名为country_code,同时呢,我们也以定义一个属性为country_code作为主键,如下:

@Entity
public class Zip { //所属国家编码
@Id
@Column(length = 20)
private String country_code; @ManyToOne
@JoinColumn(name = "country_code")
private Country country; //城市名称
@Column
private String city_name; //城市邮编
@Column
private String code; public void setCountry_code(String country_code) {
this.country_code = country_code;
} public String getCountry_code() {
return country_code;
} public void setCity_name(String city_name) {
this.city_name = city_name;
} public String getCity_name() {
return city_name;
} public void setCode(String code) {
this.code = code;
} public String getCode() {
return code;
}
}

接下来我们打开会话去保存country,如下:

Country country = new Country();
country.setName("中国");
country.setIso_code("CHI"); Zip zip = new Zip();
zip.setCity_name("深圳");
zip.setCode("518000");
zip.setCountry_code(country.getIso_code());
country.setZips(Arrays.asList(zip)); session.save(country);

此时将抛出如上异常错误,因为我们显式指定外键列名为country_code,同时主键列名也为country_code,此时将映射为同一列,也就是说country_code属于共享主键,但是针对指定的主键列country_code,我们可以显式设定值,此时将引起外键列也为country_code即与country中的iso_code值不一致的问题,所以为了修正这种情况,Hibernate要求我们必须使用其中之一来进行插入、更新,而另外一个则将只读,所以我们需要将外键列设置为不允许插入和更新,如下:

看到网上一些文章对于上述insertable和updatable的设置将其解释为:可能我们会通过上述城市邮编对象(zip)来反向创建国家对象(country),因为zip并不负责创建和更新country,反之,我们只能通过country来创建和更新zip,其实没有很大的说服力,这个说法我个人认为是错误的,我个人认为:insertable和updatable与相关实体的插入和更新无关,此二者属性背后真正的意图是防止列在当前实体的插入和更新,也就是说在实体中多次映射字段时(比如上述共享主键),这两个属性将很有用,可以进一步进行修正,常见的场景为:使用组合键、使用共享主键、使用级联主键。

属性columnDefinition

我们知道对于字符串默认为长度为255且可空,下面我们将country对象中的name属性显示设置其长度为120且不可空,如下:

如下,我们通过属性columnDefinition来进一步设置其长度为100且不可空,此时映射到表中的列到底是可空还是不可空,长度到底是100还是120呢?

@Column(columnDefinition = "varchar(100) not null", length = 120)
private String name;

我们可以看到此时将以属性columnDefinition定义的为准,也就是length将会被覆盖,那是不是说明通过columnDefinition设置后都将会被覆盖,事实真的如此吗?

@Column(columnDefinition = "varchar(100) null", nullable = false, length = 120)
private String name;
create table Country (iso_code varchar(20) not null, name varchar(100) null not null, primary key (iso_code))

我们可以看到此时通过columnDefinition属性上设置可空,但是通过nullable设置为不可空,最终映射到表中的列却是不可空,这说明此时columnDefinition中的null被冗余。我们可以看到我们设置长度、可空、精度、唯一约束有两种方式,其一可以通过对应属性比如length、nullable、precision、unique设置,其二可以通过columnDefinition设置,那么为何Hibernate要同时提供这两种方式呢?它的目的是什么呢?我认为提供这两种方式说明了其灵活性,若是简单的设置(比如只设置长度)则直接使用length即可,若需全部设置,则通过columnDefinition设置来的方便。数据库DDL由:(name + columnDefinition)构成,它是物理的,即columnDefinition是生成列的DDL时使用的SQL片段,对于长度、精度、唯一约束使用columnDefinition将会被覆盖,而对于null可能被覆盖或冗余。

总结

本节我们详细讲解了列注解@Column上的属性insertable和updatable以及columnDefinition的详细使用,下一节我们讲解枚举注解,感谢您的阅读,我们下节见。

Hibernate入门之注解@Column详解的更多相关文章

  1. Hibernate配置文件和映射文件详解

    Hibernate是一个彻底的ORM(Object Relational Mapping,对象关系映射)开源框架. 我们先看一下官方文档所给出的,Hibernate 体系结构的高层视图: 其中PO=P ...

  2. 转:springmvc常用注解标签详解

    Spring5:@Autowired注解.@Resource注解和@Service注解 - IT·达人 - 博客园--这篇顺序渐进,讲得超级好--此人博客很不错http://www.cnblogs.c ...

  3. Java 注解用法详解——@SuppressWarnings

    转自: https://www.cnblogs.com/fsjohnhuang/p/4040785.html Java魔法堂:注解用法详解——@SuppressWarnings   一.前言 编码时我 ...

  4. Spring 入门 web.xml配置详解

    Spring 入门 web.xml配置详解 https://www.cnblogs.com/cczz_11/p/4363314.html https://blog.csdn.net/hellolove ...

  5. @SuppressWarnings注解用法详解

    @SuppressWarnings注解用法详解 今天来谈谈@SuppressWarnings注解的作用. J2SE 提供的最后一个批注是 @SuppressWarnings.该批注的作用是给编译器一条 ...

  6. 爬虫入门之urllib库详解(二)

    爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...

  7. 分享知识-快乐自己:Hibernate 中Criteria Query查询详解

    1):Hibernate 中Criteria Query查询详解 当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中. 此外,Hibernate还支持Cr ...

  8. Spring 注解@Value详解

    一.spring(基础10) 注解@Value详解[1] 一 配置方式 @value需要参数,这里参数可以是两种形式: [html] view plain copy @Value("#{co ...

  9. 《挑战30天C++入门极限》入门教程:实例详解C++友元

        入门教程:实例详解C++友元 在说明什么是友元之前,我们先说明一下为什么需要友元与友元的缺点: 通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为pu ...

随机推荐

  1. K - Wand(组合数+错排公式)

    N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, ...

  2. EXAM-2018-8-9

    EXAM-2018-8-9 B 水题 注意理解题意 有坑 G 博弈 观察发现 总是会进行到最后两个,或者先手取完全部,再特判一下只有一张牌的情况 H 九连环 通过找规律 我们可以得出递推式: F[n] ...

  3. Introduction to Differential Equations,Michael E.Taylor,Page 3,4 注记

    此文是对 [Introduction to Differential Equations,Michael E.Taylor] 第3页的一个注记.在该页中,作者给了微分方程$$\frac{dx}{dt} ...

  4. sql查询语句解析过程--根据网络资料整理

    查询语句: (8)SELECT(9)DISTINCT(11)<TopNum> <selectlist> (1)FROM<left_table> (3)<joi ...

  5. 关于MyBatis的运行原理(转载)

    1.获取sqlSessionFactory对象: 解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSessionFactory: 注意: ...

  6. Pulsar、ZooKeeper、BookKeeper 作用简述

    Pulsar:采取了存储计算分离的技术ZooKeeper 集群的作用和在 Kafka 中是一样的,都是被用来存储元数据.BookKeeper 集群则被用来存储消息数据.BookKeeper 有点儿类似 ...

  7. 数据结构与算法 python课后题(未完成)

    挖一个坑,先立个flag,后面慢慢填坑. 先放个其它人写的链接

  8. python--包package、模块module、类Class、Mixin类(未完成)

    包package>模块module>类Class(包含了属性.方法.实例等概念) 模式一:一个包下面有多个py文件,即多个模块module 模式二:一个包下面包含多个子包packages ...

  9. Spring常见的两种增强方式

    一.编程式增强 不借助spring的配置,通过自己实例化对象来实现的增强方式 创建增强类,需要实现你需要的增强接口,(只有实现了该接口,这个类就是一个通知)) /** * 增强类 */ public ...

  10. flink分层 api

    最底层的processFunction 功能强大,使用复杂 中间层的DataSet api map reduce ...一些基本运算api 中上层的tableAPI 最上层 SQL 两个相似,只是写法 ...