代码之家  ›  专栏  ›  技术社区  ›  Ian Dallas

如何阻止Hibernate尝试更新一对多overjoin表

  •  1
  • Ian Dallas  · 技术社区  · 15 年前

    好吧,我在Hibernate映射和获取所需行为方面有点问题。

    基本上我有以下Hibernate映射:

    <hibernate-mapping>
        <class name="com.package.Person" table="PERSON" schema="MYSCHEMA" lazy="false">
            <id name="personId" column="PERSON_ID" type="java.lang.Long">
                <generator class="sequence">
                    <param name="sequence">PERSON_ID_SEQ</param>
                </generator>
            </id>
    
            <property name="firstName" type="string" column="FIRST_NAME">
            <property name="lastName" type="string" column="LAST_NAME">
            <property name="age" type="int" column="AGE">
    
            <set name="skills" table="PERSON_SKILL" cascade="all-delete-orphan">
                <key>
                    <column name="PERSON_ID" precision="12" scale="0" not-null="true"/>
                </key>
                <many-to-many column="SKILL_ID" unique="true" class="com.package.Skill"/>
            </set>
        </class>
    </hibernate-mapping>
    
    
    <hibernate-mapping>
        <class name="com.package.Skill" table="SKILL" schema="MYSCHEMA">
            <id name="skillId" column="SKILL_ID" type="java.lang.Long">
                <generator class="sequence">
                    <param name="sequence">SKILL_ID_SEQ</param>
                </generator>
            </id>
            <property name="description" type="string" column="DESCRIPTION">
        </class>
    </hibernate-mapping>
    

    假设我已经在技能表中填充了一些技能。现在,当我创建一个新的人时,我想通过设置技能的ID,将他们与技能表中已经存在的一组技能相关联。例如:

    Person p = new Person();
    p.setFirstName("John");
    p.setLastName("Doe");
    p.setAge(55);
    
    //Skill with id=2 is already in the skill table
    Skill s = new Skill()
    s.setSkillId(2L);
    
    p.setSkills(new HashSet<Skill>(Arrays.asList(s)));
    PersonDao.saveOrUpdate(p);
    

    但是,如果我尝试这样做,我会得到一个错误:

    WARN (org.slf4j.impl.JCLLoggerAdapter:357) - SQL Error: 1407, SQLState: 72000
    ERROR (org.slf4j.impl.JCLLoggerAdapter:454) - ORA-01407: cannot update ("MYSCHEMA"."SKILL"."DESCRIPTION") to NULL
    
    ERROR (org.slf4j.impl.JCLLoggerAdapter:532) - Could not synchronize database state with session
    org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
    

    我之所以会出现这个错误,我想是因为Hibernate发现Id为2的技能已经将其描述“更新”为null(因为我从未设置过它)并试图更新它。但我不想Hibernate更新这个。我要它做的是插入新的Person p,并将一条记录插入到连接表Person\u SKILL中,该记录将p与id=2的SKILL表中的SKILL匹配,而不接触SKILL表。

    到底有没有办法达到这个目的?

    2 回复  |  直到 15 年前
        1
  •  1
  •   matt b    15 年前

    而不是自己创建技能对象:

    //Skill with id=2 is already in the skill table
    Skill s = new Skill()
    s.setSkillId(2L);
    p.setSkills(new HashSet<Skill>(Arrays.asList(s)));
    

    您应该从Hibernate会话中检索它:

    Skill s = (Skill) session.get(Skill.class, 2L);
    p.setSkills(new HashSet<Skill>(Arrays.asList(s)));
    

    通过这种方式,会话认为 p.skills persistent, and not transient .

        2
  •  1
  •   Pascal Thivent    15 年前

    如果 all-delete-orphan

    但正确的方法是加载所需的 Skill 并将其添加到 Person .