草庐IT

java - hibernate 更新JPA外键

coder 2024-03-05 原文

我的 jpa 如下所示

public class TESTClass implements Serializable {

    ...

    private String name;

    @EmbeddedId
    protected IssTESTPK issTESTPK;

    @ManyToOne(optional=false)
    @JoinColumns({
        @JoinColumn(name="DIVISION_CODE", referencedColumnName="DIVISION_CODE", nullable=false, insertable=false, updatable=false), 
        @JoinColumn(name="SURVEY_NUM", referencedColumnName="SURVEY_NUM", nullable=false, insertable=false, updatable=false)})
    private IssDivision issDivision;

}

如果我更改“名称”并调用合并,它能够更新到数据库中,但是当我更改 issDivision 并调用合并时,它不会更新数据库。如何解决这个问题?


这与我使用的是 embededId(复合主键)有关吗?

已更新

如果我设置 upadted=true,我会得到以下错误

ERROR - ContextLoader.initWebApplicationContext(215) | Context initialization fa
iled
org.springframework.beans.factory.BeanCreationException: Error creating bean wit
h name 'sessionFactory' defined in ServletContext resource [/WEB-INF/application
Context.xml]: Invocation of init method failed; nested exception is org.hibernat
e.MappingException: Repeated column in mapping for entity: com.compay.test.model
.TESTClass column: SURVEY_NUM (should be mapped with insert="false" update="fa
lse")
        at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.createBean(AbstractAutowireCapableBeanFactory.java:380)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb
ject(AbstractBeanFactory.java:264)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr
y.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBe
an(AbstractBeanFactory.java:261)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
(AbstractBeanFactory.java:185)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
(AbstractBeanFactory.java:164)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.
preInstantiateSingletons(DefaultListableBeanFactory.java:423)
        at org.springframework.context.support.AbstractApplicationContext.finish
BeanFactoryInitialization(AbstractApplicationContext.java:728)
        at org.springframework.context.support.AbstractApplicationContext.refres
h(AbstractApplicationContext.java:380)
        at org.springframework.web.context.ContextLoader.createWebApplicationCon
text(ContextLoader.java:255)
        at org.springframework.web.context.ContextLoader.initWebApplicationConte
xt(ContextLoader.java:199)
        at org.springframework.web.context.ContextLoaderListener.contextInitiali
zed(ContextLoaderListener.java:45)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContex
t.java:3843)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:4
342)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase
.java:791)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:77
1)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)

        at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.ja
va:627)
        at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.j
ava:553)
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488
)
        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java
:311)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(Lifecycl
eSupport.java:117)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)

        at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)

        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443
)
        at org.apache.catalina.core.StandardService.start(StandardService.java:5
16)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:710
)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.

最佳答案

好吧,让我们看看

您的异常(和著名)消息是

repeated column in mapping for entity:
column: SURVEY_NUM (should be mapped with insert="false" update="false")

SURVEY_NUM 列位于何处?

issDivision 字段存储一个名为 SURVEY_NUM 的外键列

@ManyToOne
@JoinColumns({
    @JoinColumn(name="DIVISION_CODE", referencedColumnName="DIVISION_CODE", insertable=false, updatable=false), 
    @JoinColumn(name="SURVEY_NUM", referencedColumnName="SURVEY_NUM", insertable=false, updatable=false)})
private IssDivision issDivision;

现在,查看以下映射(查看 id 和 accountNumber 共享同一列)

@Entity
public class Account {

    private Integer id;

    private Integer accountNumber;

    @Id
    @Column(name="ACCOUNT_NUMBER")
    public Integer getId() {
        return this.id;
    }

    @Column(name="ACCOUNT_NUMBER")
    public Integer getAccountNumber() {
        return this.accountNumber;
    }

}

现在让我们做如下

Account account = new Account();
account.setId(127359);
account.setAccountNumber(null);

entityManager.persist(account);

Hibernate 会问你

Which property should i persist whether both properties shares the same column ??? And as i can see, id property stores a non-null value and accountNumber a null value.

我应该执行这样的查询吗???

INSERT INTO ACCOUNT (ACCOUNT_NUMBER, ACCOUNT_NUMBER) VALUES (127359, NULL);

没有意义。因此,这是一个错误的SQL查询;

正因为如此,你看到了这个好消息

repeated column... blah, blah, blah... (should be mapped with insert="false" update="false")

所以我想您名为 IssTESTPK 的复合主键还存储名为 SURVEY_NUM 的列。 这不是一个好主意,您将复合主键属性定义为 insert="false"update="false"。避免很多头痛。

请记住:当多个属性共享同一列时,将其中之一定义为 insertable=false、updatable=false。 没有别的

我认为你的复合主键类应该是这样的

@Embeddable
public class IssTESTPK implements Serializable {

    // Ops... Our missing field which causes our Exception (repeated column... blah, blah, blah...)
    @Column(name="SURVEY_NUM", nullable=false)
    private Integer property;

    private Integer otherProperty;

    private Integer anotherProperty;

    // required no-arg constructor
    public IssTESTPK() {}

    // You must implement equals and hashcode
    public boolean equals(Object o) {
        if(o == null)
            return false;

        if(!(o instanceof IssTESTPK))
            return false;

        IssTESTPK other = (IssTESTPK) o;
        if(!(getProperty().equals(other.getProperty())))
            return false;
        if(!(getOtherProperty().equals(other.getOtherProperty())))
            return false;
        if(!(getAnotherProperty().equals(other.getAnotherProperty())))
            return false;

        return true;
    }

    // NetBeans or Eclipse will worry about it
    public int hashcode() {
        // hashcode code goes here
    }

}

更新


继续之前

Hibernate does not support automatic generation of compound primary key

必须在保存前提供它的值。记在心里

让我们看看员工复合主键

@Embeddable
public class EmployeeId implements Serializable {

    @Column(name="EMPLOYEE_NUMBER")
    private String employeeNumber;

    @Column(name="SURVEY_NUMBER")
    private BigInteger surveyNumber;

    // getter's and setter's

    // equals and hashcode

}

在保存 Employee 之前,您必须提供它的值。上面说了,Hibernate不支持自动生成复合主键

Hibernate 不允许您更新(复合)主键这没有意义。

其值不能为空

所以,根据上面的描述,我们的EmployeeId可以写成

@Embeddable
public class EmployeeId implements Serializable {

    @Column(name="EMPLOYEE_NUMBER", nullable=false, updatable=false)
    private String employeeNumber;

    @Column(name="SURVEY_NUMBER", nullable=false, updatable=false)
    private BigInteger surveyNumber;

    // getter's and setter's

    // equals and hashcode

}

如前所述

when more than one property shares the same column, define one of them as insertable=false, updatable=false. Nothing else

但是我们不能将复合主键属性标记为 insertable=false, updatable=false 因为 Hibernate 使用它来保存我们的实体

由于 Hibernate 将使用名为 surveyNumber 的复合主键属性(及其 SURVEY_NUMBER 列)对数据库执行 SQL 操作,因此我们需要重写我们的 @ManyToOne 分部属性(及其名为 SURVEY_NUMBER 的外键列)为 insertable=假的,可更新的=假的

// Employee.java

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
    @JoinColumn(name="DIVISION_CODE", referencedColumnName="DIVISION_CODE"),
    @JoinColumn(name="SURVEY_NUMBER", referencedColumnName="SURVEY_NUMBER", insertable=false, updatable=false)})
private Division division;

当您有复合外键时,我们不能混合可插入-不可插入或可更新-不可更新。

有点像

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
    // I can be updatable
    @JoinColumn(name="DIVISION_CODE", referencedColumnName="DIVISION_CODE", insertable=false),
    // And i can be insertable
    @JoinColumn(name="SURVEY_NUMBER", referencedColumnName="SURVEY_NUMBER", updatable=false)})
private Division division;

否则,Hibernate 会报错

Mixing insertable and non insertable columns in a property is not allowed

正因为如此,它的名为 DIVISION_CODE 的复合外键列也应该标记为 insertable=false, updatable=false 以避免上面显示的异常

// Employee.java

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
    @JoinColumn(name="DIVISION_CODE", referencedColumnName="DIVISION_CODE", insertable=false, updatable=false),
    @JoinColumn(name="SURVEY_NUMBER", referencedColumnName="SURVEY_NUMBER", insertable=false, updatable=false)})
private Division division;

由于我们无法再更新 DIVISION_CODE 列,我们的除法属性表现得像常量。然后,您考虑创建一个名为 divisionCode 的新属性来更改 DIVISION_CODE 列,如下所示

// Employee.java

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
    @JoinColumn(name="DIVISION_CODE", referencedColumnName="DIVISION_CODE", insertable=false, updatable=false),
    @JoinColumn(name="SURVEY_NUMBER", referencedColumnName="SURVEY_NUMBER", insertable=false, updatable=false)})
private Division division;

// Wow, now i expect i can change the value of DIVISION_CODE column
@Column(name="DIVISION_CODE")
private BigInteger divisionCode;

好吧,让我们看看。假设我们有以下 DIVISION TABLE

DIVISION TABLE
DIVISION_CODE     SURVEY_NUMBER
1                 10
2                 11
3                 12
4                 13
5                 14

记住:Division 和 Employee 之间有一个外键约束

你想到

I can not change division property because of insertable=false, updatable=false. But i can change divisionCode property (and its DIVISION_CODE column) as a way to change the foreign key column called DIVISION_CODE

您执行以下代码

员工.setDivisionCode(7);

哇哦,请参阅上面的 DIVISION_TABLE。 DIVISION_CODE 列中是否有某个值等于 7?

答案很明确:否(您会看到违反约束)

所以,这是一个不一致的映射。 Hibernate 不允许这样做。

问候,

关于java - hibernate 更新JPA外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2468106/

有关java - hibernate 更新JPA外键的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  4. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  5. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  6. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  7. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  8. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

随机推荐