[hibernate-issues] [Hibernate-JIRA] Created: (HBX-1179) <one-to-one> should not generate Sets

Joachim Durchholz (JIRA) noreply at atlassian.com
Fri Mar 11 11:33:08 EST 2011


<one-to-one> should not generate Sets
-------------------------------------

                 Key: HBX-1179
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HBX-1179
             Project: Hibernate Tools
          Issue Type: Bug
          Components: reverse-engineer
         Environment: Hibernate Tools version as reported by Eclipse: 3.3.0.v20101016-0359-H111-Beta1
Feel free to identify the matching release numbers, I can't :-/
            Reporter: Joachim Durchholz


Hibernate tools does not always recognize one-to-one associations as such, even if specified as <one-to-one> in hibernate.reveng.xml.

1. It should generally not silently fall back to one-to-many or many-to-one if it determines that one-to-one is not possible; it should report an error instead. (This allows programmers to correct the database and/or the hibernate.reveng.xml: if it's really a one-to-many, they can move the association to the other table and make it many-to-one; if it should be one-to-one, they can add the missing constraints, giving Hibernate better information about the database schema actually in place.)
2. In the following test case, it does not recognize the relationship as one-to-one even though it is, erroneously generating a Set for the <inverse-one-to-one> direction instead of a backlink.

Workarounds:
A) Use <inverse-one-to-one exclude="true"/> to prevent Set creation. Works if you don't need the backlink.
B) Have a backlink field in the target table. Create two one-to-one associations, one for each direction, and use <inverse-one-to-one exclude="true"/>.
C) Do not reverse engineer the one-to-one association at all and use Criteria, HQL, or SQL to navigate the link.
D) Subclass DefaultReverseEngineeringStrategy and override isOneToOne() for that particular association.

Test case:

Table creation (Oracle 10g)

CREATE TABLE "HF_DI_BVKRIT" (
  "BKID" NUMBER(27,0) NOT NULL ENABLE,
  "VERSION" NUMBER(18,0) DEFAULT 0 NOT NULL ENABLE,
  "BKNAME" VARCHAR2(40) NOT NULL ENABLE
) ;
ALTER TABLE "HF_DI_BVKRIT" ADD CONSTRAINT "HF_DI_BVKRIT_PK"
  PRIMARY KEY ("BKID") ENABLE;

CREATE TABLE "HF_DI_BVKOPF" (
  "BVID" NUMBER(10,0) NOT NULL ENABLE,
  "VERSION" NUMBER(18,0) DEFAULT 0 NOT NULL ENABLE,
  "BVBKID" NUMBER(27,0) NOT NULL ENABLE,
  "BVGPRS" NUMBER(8,2)
) ;
ALTER TABLE "HF_DI_BVKOPF" ADD CONSTRAINT "HF_DI_BVKOPF_PK"
  PRIMARY KEY ("BVID") ENABLE;
ALTER TABLE "HF_DI_BVKOPF" ADD CONSTRAINT "HF_DI_BVKOPF_UK"
  UNIQUE ("BVBKID") ENABLE;
ALTER TABLE "HF_DI_BVKOPF" ADD CONSTRAINT "HF_DI_BVKOPF_FK_BVKRIT"
  FOREIGN KEY ("BVBKID") REFERENCES "HF_DI_BVKRIT" ("BKID") ENABLE;

Relevant hibernate.reveng.xml section:

  <table name="HF_DI_BVKOPF">
    <column name="VERSION" type="long"></column>
    <foreign-key constraint-name="HF_DI_BVKOPF_FK_BVKRIT">
      <one-to-one />
      <inverse-one-to-one />
    </foreign-key>
  </table>

Generated Java classes:

public class HfDiBvkrit implements java.io.Serializable {
  private BigInteger bkid;
  private long version;
  private String bkname;
  private Set <HfDiBvkopf> hfDiBvkopfs = new HashSet <HfDiBvkopf> (0);
  // The above line should have been generated as:
  // private HfDiBvkopf hfDiBvkopf;
  ...
}
public class HfDiBvkopf implements java.io.Serializable {
  private BigInteger bvid;
  private long version;
  private HfDiBvkrit hfDiBvkrit;
  private BigDecimal bvgprs;
  ...
}

Reasoning why this should be a one-to-one association (hopefully I didn't make too many errors reversing the roles of left and right table):

There is a unique key on BVKOPF.BVBKID.
I.e. a BVKRIT record can find at most one BVKOPF with a BVBKID that matches its BVKRIT.BKID.
The BVKOPF-BVKRIT association hence must be one-to-*. (1)

There is a foreign key from BVKOPF.BVBKID to BVKRIT.BKID.
BKID is a unique key in BVKRIT (it also happens to be the primary key, but that's irrelevant here).
I.e. a BVKOPF record can find at most one BVKRIT with a BKID that matches its BVKOPF.BVBKID.
The BVKOPF-BVKRIT association hence must be *-to-one. (2)

Combining (1) and (2) gives "must be one-to-one", q.e.d.

See also https://forum.hibernate.org/viewtopic.php?f=6&t=1009989&start=0

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list