0

There are two entity classes:

@Entity
public class Person {
    @ManyToOne(cascade = CascadeType.PERSIST)
    private Hobby hobby;
}


@Entity
public class Hobby {
    private String hobby;
}

The Person.hobby field should take only values, that are found in the "hobby" table. So I want to define a set of Hobbies, from which a Person can choose exactly one. Of course, one Hobby can be shared by many Persons and the "hobby" table should not be altered when a new Person with a Hobby is added.

In fact this would realize an enumeration, which is not coded in Java, but defined in the underlying database "hobby" table. So if new Hobbies have to be added, only the database and not the codebase have to be changed.

How is this realized with hibernate (4.3) and JPA annotations?

1 Answers1

0

You already did it!

By doing the @ManyToOne, the Person.hobby column becomes a foreign key to the Hobby.id.

You also need to add an id in the Hobby, but I assume you already have that.

Another thing to consider is that you need to load the Hobby entities from the EntityManager before using it in the Person class, and not create a new Hobby() object if you want to reuse an existing Hobby.

Hobby hobby = entityManager.findByName(hobbyName)
person.setHobby(hobby)

To make sure you don't introduce a new hobby by accident, you could add a unique constraint on the hobbyName.

An alternative would be to make hobbyName the actual primary key of the Hobby class. But then you need a merge call to create an object that hibernate knows how to handle in transactions etc.

Hobby hobby = new Hobby(hobbyName)
hobby = entityManager.merge(hobby)
person.setHobby(hobby)

In theory, this would avoid an SQL Query. But this is considered bad practice, according to this: merging a detached or new entity with an existing entity in hibernate/jpa best practice question .

Community
  • 1
  • 1
GeertPt
  • 16,398
  • 2
  • 37
  • 61
  • Thanks, @greyfairer. I left out the id fields to strip the code. The foreign key relationship is there, indeed. Loading the "hobby" table contents makes sense. I don't, and that fills the table with the same Hobby over and over. It would be nice, however, if hibernate would take care of that. I'm looking for something like this, maybe: Make `String Hobby.hobby` the primary key (i.e. @Id) and have Hibernate automatically take this reference, if a Hobby with the same value of Hobby.hobby is inserted. Is that considered good practise, or even possible? This would get me close to a real Enum. – running hedgehog Sep 14 '16 at 13:38
  • I just added code example, and an example of using the hobbyName as a primary key. – GeertPt Sep 14 '16 at 13:59
  • Totally makes sense now. Thanks again! – running hedgehog Sep 15 '16 at 08:55