Unidirectional @OneToOne primary key association

Today I want to show you an example of unidirectional one to one association using primary key. It can be a little bit difficult for beginners to setup such association but I will try my best to explain all aspects in a clear way. For this tutorial I choose MySQL as a database, also I will use Hibernate and JPA annotations.

Firstly, I need two tables in the DB with a one to one relationship. Tables are pretty primitive, because the tutorial must be as simple as possible. The first table is “authors” and the second one is “biographies“. Primary key from the “authors” table is a shared primary key, so the “biographies” table has a foreign key linked to the “id” column of the “authors” table. Reading all this can be confused, so let’s give a look at the tables scheme.

MySQL one to one relationship

The illustration of the tables are good but below I will provide a code for the tables creation:

CREATE TABLE `authors` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `biographies` (
  `author_id` int(6) NOT NULL,
  `information` varchar(100) NOT NULL,
  KEY `author_bio` (`author_id`),
  CONSTRAINT `author_bio` FOREIGN KEY (`author_id`) REFERENCES `authors` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Now it’s time to create POJOs which will represent our tables from the database. The first will be a Biography class, because it doesn’t require any other previously created class.

import javax.persistence.*;

@Entity
@Table(name="biographies")
public class Biography {
	
	@Id
	@Column(name="author_id")
	private Integer authorId;
	
	private String information;

	public Integer getAuthorId() {
		return authorId;
	}

	public void setAuthorId(Integer authorId) {
		this.authorId = authorId;
	}

	public String getInformation() {
		return information;
	}

	public void setInformation(String information) {
		this.information = information;
	}
	
}

I can’t underline something special in the Biography class. Everything is obvious. Let’s move on, the next class is the Author’s one.

import javax.persistence.*;

@Entity
@Table(name="authors")
public class Author {

	@Id
	@GeneratedValue
	private Integer id;
	
	private String name;
	
	@OneToOne(cascade=CascadeType.ALL)
	@PrimaryKeyJoinColumn
	private Biography biography;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Biography getBiography() {
		return biography;
	}

	public void setBiography(Biography biography) {
		this.biography = biography;
	}
	
}

Here I need to stop and say several important things:

  • Author class is an owning side of association (Unidirectional associations doesn’t have inverse side). Owning side is determined by existence of primary key.
  • Unidirectional association implies existence of reference just in one class (In our case it’s @OneToONe annotation in Author class).
  • The @PrimaryKeyJoinColumn annotation specifies the primary key column that is used as a foreign key to join to another table.

After so serious conversation it’s time to test the code in action. I will omit Hibernate configuration etc since it was discussed earlier.

...
	public static void main(String[] args) {

		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		
		Author author = new Author();
		author.setName("Jack London");
		
		session.persist(author);
		
		Biography biography = new Biography();
		biography.setInformation("Jack London was an American author...");
		biography.setAuthorId(author.getId());
		
		author.setBiography(biography);
		
		session.save(author);
		
		session.getTransaction().commit();
		
		session.close();

	}
...

Notice that firstly I have persisted the author’s object to get its id for the further usage. When I started working with the biography object I set to it the id of already persisted author object. Then I added the biography object to the author, saved the author object and finally I committed the transaction.

You can see the results of the code execution in the database. Just browse appropriate tables and watch the record about Jack London. Thats all what I want to say about unidirectional one to one associations in Hibernate.

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS
  • mike haefele

    Having to persist the author before assigning a Biography seems like a big limitation.

    For example, say I have a screen to create a new author and that screen allows me to enter biography information as well.
    I certainly don’t want to persist author until I’m done, as the user might hit cancel.
    But I do need a biography object to store the information entered.

    Only thing I can think of here is:
    1. Create an author with a biography.
    2. Allow the user to edit the author and biography.
    3. When the user clicks save, store the biography in a local variable and set the authors biography to null.
    4. Persist the author.
    5. Set the authors biography back to the one you saved and assign the id as in the example.

    Step 3-5 seem like this can’t be the right way to do it..

    I specifically point out this use case because OneToOne associations are a great way to factor an overly large table into smaller tables. Requiring the developer to track down when the pieces that are factored out need to be created makes this more difficult.

    I’d much prefer
    private Biography biography = new Biography();
    which would mean the developer doesn’t need to worry about when this is or is not initialized.
    It also allows us to designate biography to be @Nonnull.

    • Fruzenshtein

      Mike, thanks for the comment
      You right, but in this tutorial I just show a basic way of usage the @OneToOne annotation

  • tariq

    thanks helpful for me

  • Balaji

    Nice Post! Helped me.