будьте в спящем режиме обновление внешний ключ JPA

Мой 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.
9
задан Michael Easter 27 March 2010 в 17:21
поделиться

3 ответа

Что ж, давайте посмотрим

Ваше исключительное (и известное) сообщение:

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 спросит вас

Какое свойство мне следует сохранить , будут ли оба свойства использовать один и тот же столбец ? ?? И, как я вижу, свойство id хранит ненулевое значение, а accountNumber - нулевое значение.

Следует ли мне выполнять такой запрос ???

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

Это не имеет смысла. Следовательно, это неправильный запрос SQL;

Из-за этого вы видите это красивое сообщение

: повторяющийся столбец ... бла, бла, бла ... (должно быть сопоставлено с помощью 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 не поддерживает автоматическое создание составного первичного ключа

Вы должен предоставить свои значения перед сохранением. Помните об этом

Давайте посмотрим составной первичный ключ сотрудника

@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

}

Перед сохранением сотрудника вы должны указать его значения. Как было сказано выше, 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

}

Как сказано

, когда более одного свойства используют один и тот же столбец, определите одно из их как insertable = false, updatable = false. Ничего другого

Но мы не можем пометить свойство составного первичного ключа как insertable = false, updatable = false , потому что Hibernate использует его для сохранения нашей сущности

Поскольку Hibernate будет использовать наше свойство составного первичного ключа с именем surveyNumber (и его столбцом SURVEY_NUMBER) для выполнения операции SQL с базой данных, нам нужно переписать наше свойство деления @ManyToOne (и его столбец внешнего ключа с именем SURVEY_NUMBER) как insertable = false, updatable = false

// 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 будет жаловаться

Смешивание вставляемых и не вставляемых столбцов в свойстве запрещено

Из-за этого его столбец составного внешнего ключа с именем 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_CODE     SURVEY_NUMBER
1                 10
2                 11
3                 12
4                 13
5                 14

, помните: существует ограничение внешнего ключа между подразделением и сотрудником

Вы думаете о

Я не могу изменить свойство подразделения из-за insertable = false, updatable = false. Но я могу изменить свойство DivisionCode (и его столбец DIVISION_CODE) как способ изменить столбец внешнего ключа с именем DIVISION_CODE

Вы выполните следующий код

employee.setDivisionCode (7);

Вау, смотрите выше в DIVISION_TABLE. Имеется ли какое-то значение в столбце DIVISION_CODE, равное 7?

ответ ясен: нет (вы увидите НАРУШЕНИЕ ОГРАНИЧЕНИЙ)

Итак, это несовместимое отображение . Hibernate не позволяет этого.

с уважением,

15
ответ дан 4 December 2019 в 11:41
поделиться

Это потому, что вы используете updatable = false . Его удаление может привести к другим проблемам, о которых я не могу предположить, не зная вашего полного сопоставления.

Установите обновляемый и вставляемый в false в классе Embeddable и удалите их из столбцов соединения

{ {1}}
2
ответ дан 4 December 2019 в 11:41
поделиться

Я нашел обходной путь, но мне хотелось бы услышать от вас всех, можно ли использовать эта техника. Я изменил класс сущности на ..

public class TESTClass implements Serializable {

...
private String name;
@EmbeddedId
protected IssTESTPK issTESTPK;

    @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)})
    @ManyToOne(optional = false)
    private IssDivision issDivision;   //since this is not merge

       @Basic(optional = false)
    @Column(name = "DIVISION_CODE")
    private String divisionCode;  //i add this

}

Я добавил свойство «DivisionCode», хотя оно дублировалось внутри объекта issDivision. но это обходной путь, который я могу обновить "DIVISION_CODDE" во время слияния

1
ответ дан 4 December 2019 в 11:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: