jpa无外键配置
在用jpa这种orm框架时,有时我们实体对象存在关联关系,但实际的业务场景可能不需要用jpa来控制数据库创建数据表之间的关联约束,这时我们就需要消除掉数据库表与表之间的外键关联。
但jpa在处理建立外键时存在一些问题,在stackoverflow上搜索了相关的jpa创建实体对象关联关系但不建立外键这一系列问题后,发现这个是jpa在处理外键时存在一定的bug,官方给出的答复是在hibernate 5.x会解决掉这个问题,但是经验证5.x的版本这个问题依旧存在。下面给出这个问题的解释以及这个问题如何解决。
下面会以techer和student对象来举例,teacher和student存在一对多关系,一个teacher关联多个student。
1.teacher与student设置外键关系
teacher和student之间通过@OneToMany和@ManyToOne建立外键关联关系
teacher:
@Entity
@Table(name = "TEACHER")
public class Teacher extends BaseDomain {
@Id()
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id; @Column
private String name; @OneToMany(mappedBy = "teacher")
private List<Student> students; //getter&setter...
}
student:
@Entity
@Table(name = "STUDENT")
public class Student extends BaseDomain { @Id()
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id; @Column
private String name; @ManyToOne
@JoinColumn(name = "tid")
private Teacher teacher; //getter&setter...
}
数据库生成表结果:
CREATE TABLE “public”.”student” (
“id” int8 DEFAULT nextval(‘student_id_seq’::regclass) NOT NULL,
“name” varchar(255) COLLATE “default”,
“teacher_id” int8,
CONSTRAINT “student_pkey” PRIMARY KEY (“id”),
CONSTRAINT “fk3y5qg5r9ewc48x7ek8lx5ua8h” FOREIGN KEY (“teacher_id”) REFERENCES “public”.”teacher” > (“id”) ON DELETE NO ACTION ON UPDATE NO ACTION
)
WITH (OIDS=FALSE)
;
ALTER TABLE “public”.”student” OWNER TO “postgres”;
可以看到设置了外键”fk3y5qg5r9ewc48x7ek8lx5ua8h” FOREIGN KEY (“teacher_id”)
2.只在student端加上@ForeignKey
student
@Entity
@Table(name = "STUDENT")
public class Student extends BaseDomain { @Id()
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id; @Column
private String name; @ManyToOne
@JoinColumn(name = "tid",foreignKey = @ForeignKey(name = "none",value = ConstraintMode.NO_CONSTRAINT))
private Teacher teacher; //setter&getter
}
加上该注解之后,根据这个注解说明是可以去掉外键关联关系,但发现加上后然并卵,外键还是没有去掉。这里需要说明其中@ForeignKey的value值由如下代码所示几种情况:
/**
* Used to control the application of a constraint.
*
* @since JPA 2.1
*/
public enum ConstraintMode {
/**
* Apply the constraint.
*/
CONSTRAINT,
/**
* Do not apply the constraint.
*/
NO_CONSTRAINT,
/**
* Use the provider-defined default behavior.
*/
PROVIDER_DEFAULT
}
3.在teacher端加入@org.hibernate.annotations.ForeignKey(name = “none”)
在一的这端加上@org.hibernate.annotations.ForeignKey(name = “none”)这个被jpa废弃的注解。加上之前在student中设置的@ForeignKey(注意这个是javax.persistence包下的),可以去掉外键关联
teacher:
@Entity
@Table(name = "TEACHER")
public class Teacher extends BaseDomain {
@Id()
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id; @Column
private String name; @OneToMany(mappedBy = "teacher")
@org.hibernate.annotations.ForeignKey(name = "none")
private List<Student> students; //getter&setter...
}
结果:
CREATE TABLE “public”.”student” (
“id” int8 DEFAULT nextval(‘student_id_seq’::regclass) NOT NULL,
“createdtime” timestamp(6),
“name” varchar(255) COLLATE “default”,
“version” int4,
“tid” int8,
CONSTRAINT “student_pkey” PRIMARY KEY (“id”)
)
WITH (OIDS=FALSE)
;
ALTER TABLE “public”.”student” OWNER TO “postgres”;
可以看到student表中原来关联teacher的外键没了,说明该注解起作用。
4.需要注意的坑
1.如果teacher(1的这端)有student列表(多的这端),像这样:
@OneToMany(mappedBy = "teacher")
@org.hibernate.annotations.ForeignKey(name = "none")
private List<Student> students;
如果要去掉外键关联关系,student端也需要像在2小结提到样需要加上@JoinColumn(name = “tid”,foreignKey = @ForeignKey(name = “none”,value = ConstraintMode.NO_CONSTRAINT)),但此时你会发现其中@ForeignKey中value的值不管你设置为ConstraintMode.NO_CONSTRAINT还是ConstraintMode.CONSTRAINT,数据库都不会设置外键(这个是特么的真奇怪)。但是就是不管怎样,你就是不能不设置@ForeignKey,并且你还必须要设置其中的值不能为默认值,不然就是要生成外键。这里贴下@ForeignKey的源码:
@Target({})
@Retention(RUNTIME)
public @interface ForeignKey {
/**
* (Optional) The name of the foreign key constraint. Defaults to a provider-generated name.
*
* @return The foreign key name
*/
String name() default "";
/**
* (Optional) The foreign key constraint definition. Default is provider defined. If the value of
* disableForeignKey is true, the provider must not generate a foreign key constraint.
*
* @return The foreign key definition
*/
String foreignKeyDefinition() default "";
/**
* (Optional) Used to specify whether a foreign key constraint should be generated when schema generation is in effect.
*/
ConstraintMode value() default ConstraintMode.CONSTRAINT;
}
真的是X了狗了。。。我表示久久不能理解。。。
2.teacher(1这端)没有student列表或者student列表被@Transient所修饰,像这样:
@OneToMany(mappedBy = "teacher")
@Transient
private List<Student> students;
那么也是无论你在student端设置ConstraintMode的值,都不会设置外键.but!!!你就是不能不在student端(多的这端)设置@JoinColumn(name=”tid”,foreignKey=@ForeignKey(name=”none”,value=ConstraintMode.NO_CONSTRAINT)),否则也是会生成外键
总结
所以要使数据表中没有外键关联关系。
1.当两边都有关联关系字段,1的这端利用@org.hibernate.annotations.ForeignKey(name = “none”),多的那端在JoinColumn中加上foreignKey = @ForeignKey(name = “none”,value = ConstraintMode.NO_CONSTRAINT)
2.当只有多的那端有关联字段,一的那段没有关联字段或者关联字段被@Transient所修饰,请在多的那端在JoinColumn中加上foreignKey = @ForeignKey(name = “none”,value = ConstraintMode.NO_CONSTRAINT)
最后需要说明的是@org.hibernate.annotations.ForeignKey(name = “none”)这个注解之后可能会在之后的版本会被直接移除掉,所以更新jar包的时候需要注意下。
参考资料:
①.https://hibernate.atlassian.net/browse/HHH-8805
②.https://hibernate.atlassian.net/browse/HHH-8862
jpa无外键配置的更多相关文章
- 【Hibernate】无外键多表查询
无外键多表查询时编写hql,直接使用逗号分隔表,where作为联合查询条件进行查询.查询出来的结果可为两种,List<List<Object>>或者List<Map< ...
- ruby -- 基础学习(二) 外键配置实现级联删除
该系列学习基于rails4.0 数据表:admins (id, name, address), articles (id, admin_id, title) admin_id 是表articles中的 ...
- Springboot结合Jpa的外键使用
当我们写项目的时候,总有些奇奇怪怪的理由,非让你连表查询,其实最好的就是什么都不连,数据库完全解耦 但我们还是要学习下Jpa怎么根据外键查询 (这里说下Jpa+springboot的感觉,刚开始就感觉 ...
- Kettle ETL 来进行mysql 数据同步——试验环境搭建(表中无索引,无约束,无外键连接的情况)
今天试验了如何在Kettle的图形界面(Spoon)下面来整合来mysql 数据库中位于不同数据库中的数据表中的数据. 试验用的数据表是customers: 第三方的数据集下载地址是:http://w ...
- Python3-sqlalchemy-orm 联表查询-无外键关系
#-*-coding:utf-8-*- #__author__ = "logan.xu" import sqlalchemy from sqlalchemy import crea ...
- peewee无外键连接
# 参考:https://blog.csdn.net/weixin_34273479/article/details/87587183 res = Name.select(Name, User.xxx ...
- hibernate框架学习第四天:关联关系、外键、级联等
一对多关联关系表 一方 多方(外键)实体类 一方:TeacherModel 添加多方的集合Set 多方StudentModel 添加一方的对象一方配置关系 name:一方模型中描述多方的集合对象名 c ...
- EntityFramework 外键值映射
如果在 EF OnModelCreating 中配置了实体外键映射,也就是 SQL Server 中的 ForeignKey,那么我们在添加实体的时候,主实体的主键值会自动映射到子实体的外键值,并且这 ...
- SQLServer 主键、外键、唯一等约束
主键(primary key)约束.外键(foreign key)约束.唯一(unique)约束.检查(check)约束.默认值(default)约束实例 Oracle 有如下类型的约束:NOT NU ...
随机推荐
- angular内置过滤器-filter
这篇文章来讲解一下angular内置的filter过滤器. 没错,这个过滤器的名字,就叫'filter',虽然自定义过滤器也是使用module.filter()...但是不要混淆了,这个filter就 ...
- c#,asp.net 开发 app 学习资料整理
VS2015 Apache Cordova第一个Android和IOS应用 http://www.cnblogs.com/aehyok/p/4116410.html PhoneGap:免费开源的 HT ...
- [Windows Azure] Adding Sign-On to Your Web Application Using Windows Azure AD
Adding Sign-On to Your Web Application Using Windows Azure AD 14 out of 19 rated this helpful - Rate ...
- ROC曲线(Receiver Operating Characteristic Curve)
分类模型尝试将各个实例(instance)划归到某个特定的类,而分类模型的结果一般是实数值,如逻辑回归,其结果是从0到1的实数值.这里就涉及到如何确定阈值(threshold value),使得模型结 ...
- 每日英语:Patent Wars Erupt Again in Tech Sector
The long-running patent war among the technology industry's heavyweights just grew a whole lot bigge ...
- Logistic回归分析简介
Logistic回归:实际上属于判别分析,因拥有很差的判别效率而不常用. 1. 应用范围: ① 适用于流行病学资料的危险因素分析 ② 实验室中药物的剂量-反应关系 ③ 临床试验 ...
- 进入Linux救援(rescue)模式的四大法门
原文:http://blog.51cto.com/xxrenzhe/1272838 适用场景: 当误操作修改系统启动文件/etc/fstab, /etc/rc.d/rc.sysinit时,就会造成系统 ...
- .NET ramework 4.0安装失败
1.停止Window 升级服务: 2.Windows 目录下的 SoftwareDistribution 重命名: 3.安装 .Net Framework 下面是百度上的方法,比较复杂 解决方法:1) ...
- DFI、DPI技术
废话: 因为xxoo的缘故接触到这个设备.但是就是单纯的去看并没有去研究它是个啥玩意.刚才无聊就百度科普了一波. DFI以及DPI简单通俗以自己的理解来将就是网络带宽的一种检测技术.既然是检测技术也就 ...
- 解决MYSQL ERROR 1045 (28000)问题
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) Red Hat Enterpr ...