saplingPro
saplingPro

Reputation: 21329

The concept for one-to-one mapping. Explain the mapping

How to define a One-to-One relation between 2 classes ? I think I am going wrong somewhere,conceptually. I don't know what ,but it is.

Let us suppose there are two classes named Country and PM :

Country
  int c_id
  String name_c

PM
 int c_id
 String name_pm

Now for one country, there can only be one PM and PM can belong only to one country. How do I do this in my mapping file ?

I was trying this :

<class name="pojo.Country" table="country">
      <id name="c_id">
          <generator class="increment" />
      </id>
      <property name="name_c" />
      <one-to-one class="pojo.PM" name="name_pm" />
  </class>

  <class name="pojo.PM" table="pm">
      <id name="c_id">
          <generator class="increment" />
      </id>
      <property name="name_pm"  />
  </class>

But this effete mapping does nothing than to produce an exception during run time.It says the property name_pm cannot be found inside the Country class ! But does it search inside the Country class. It should rather search inside the PM class.

Also help me accomplish my one-to-one mapping between the 2 classes. I have been trying this for some time.

Java Code:

Country

    public class Country {
    private int c_id;
    private String name_c;

    public int getC_id() {
        return c_id;
    }

    public void setC_id(int c_id) {
        this.c_id = c_id;
    }

    public String getName_c() {
        return name_c;
    }

    public void setName_c(String name_c) {
        this.name_c = name_c;
    }

}

PM

    public class PM {
    private int c_id;
    private String name_pm;

    public int getC_id() {
        return c_id;
    }

    public void setC_id(int c_id) {
        this.c_id = c_id;
    }

    public String getName_pm() {
        return name_pm;
    }

    public void setName_pm(String name_pm) {
        this.name_pm = name_pm;
    }

}

Upvotes: 0

Views: 960

Answers (2)

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123891

If part of your question is also "...I think I am going wrong somewhere,conceptually... ", I'd like to provide some explanation.

First of all, One-to-One means, that the reference is between objects (instances). Other words, there must be reference from one object to other. Not only a common simple type (i.e. String name_pm or String name_c)

Both objects should reference each other:

public class PM {
    private Country country;  // reference to an instance of the PM
    ...
}

public class Country {
    private PM pm; // reference to an instance of the Country
    ...
}

On a DB level, it is a bit more trickier. Because references are based on ID columns and we do assure us, that these two Country-PM will always belong together, we have to reuse the ID value.

So, one object will play the role of the Master, e.g. Country and the second will assign its ID based on it. If we won't follow that pattern, we cannot be sure, that there will sooner or later arise some many-to-one or many-to-many relation.

And that's why the mapping usually looks like this

<class name="pojo.Country" table="country">
    <id name="c_id">
        <generator class="increment" />
    </id>
    <property name="name_c" />
    <one-to-one class="pojo.PM" name="pm" cascade="save-update" />
</class>

<class name="pojo.PM" table="pm">
    <id name="pmid" type="java.lang.Integer">
        <column name="c_id" />
        <generator class="foreign">
           <param name="property">country</param>
        </generator>
    </id>
    <one-to-one name="country" class="pojo.Country" constrained="true" />
</class>

But one-to-one mapping is really very exceptional. I guess that mapping many-to-on on PM side (with country id reference in DB) could be more suitable. It is different approach at all, but...

Please, try to see this nice article:

Upvotes: 2

Don Roby
Don Roby

Reputation: 41135

The problem is in the relation between your xml mapping and your Java code.

If you specify

  <one-to-one class="pojo.PM" name="name_pm" />

there needs to be a field named "name_pm" in your Country POJO.

You don't have such a field.

If your Country class has a field for the corresponding PM object, that field's name should be used here.

If neither class has a reference to the other, you need to add one.

What I would probably do with your code is to add a field to country and use its name in the mapping.

public class Country {
    private int c_id;
    private String name_c;
    private PM c_pm;

    public int getC_id() {
        return c_id;
    }

    public void setC_id(int c_id) {
        this.c_id = c_id;
    }

    public String getName_c() {
        return name_c;
    }

    public void setName_c(String name_c) {
        this.name_c = name_c;
    }

    public PM getC_pm() {
        return c_pm;
    }

    public void setC_pm(PM c_PM) {
        this.c_pm = c_pm;
    }

}

Mapping:

<class name="pojo.Country" table="country">
      <id name="c_id">
          <generator class="increment" />
      </id>
      <property name="name_c" />
      <one-to-one class="pojo.PM" name="c_pm" />
</class>

Disclaimer:

I haven't tested any of this, and I'm not sure of exactly how the mapping should be done with a shared primary key. If anyone else feels like providing a tested version, I'll happily upvote another answer or let this one turn "community wiki".

Upvotes: 2

Related Questions