One to Many Hibernate/JPA example

In this article we will learn how to implement a One to Many Entity Relation between two objects in an Hibernate/JPA application.

One to Many overview

In RDBMS terms, a one-to-many relationship exists when one record in table A may be linked with many records in table B. On the other hand, one record in table B is linked to only one Record in table A.

Here’s an example which uses a One-to-Many mapping between the Table Customer (ONE) and Request (MANY).

hibernate one to many example

For the sake of simplicity, we will use H2 Database in our example application. On the other hand, if you want to use an external DB like MySQL, you can create the following Table structure for the example:

mysql> desc customer;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| name         | varchar(25)  | YES  |     | NULL    |                |
| phone_number | int(11)      | YES  |     | NULL    |                |
| address      | varchar(100) | YES  |     | NULL    |                |
| email        | varchar(50)  | YES  |     | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+
5 rows in set (0.07 sec)

mysql> desc request;
+-------------+---------+------+-----+---------+----------------+
| Field       | Type    | Null | Key | Default | Extra          |
+-------------+---------+------+-----+---------+----------------+
| id          | int(11) | NO   | PRI | NULL    | auto_increment |
| quantity    | int(11) | YES  |     | NULL    |                |
| id_customer | int(11) | YES  | MUL | NULL    |                |
+-------------+---------+------+-----+---------+----------------+

Coding the Entity Classes

To represent the One to Many Relation, we will create two Entity Classes in our project. Here’s the Customer class:

@Entity

public class Customer implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private String name;

    @NotNull
    private String email;

    @NotNull
    private String address;

    @NotNull
    @Column(name = "phone_number")
    private String phoneNumber;
  
    //bi-directional many-to-one association to Request
    @OneToMany(mappedBy="customer", cascade = CascadeType.ALL,  orphanRemoval = true)
    private List<Request> requests = new ArrayList();
 
  // getters/setters omitted for brevity
}

Next, let’s add also the Request class:

@Entity

public class Request implements Serializable {
 
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @Column
    private int quantity;

    //bi-directional many-to-one association to Customer
    @ManyToOne
    private Customer customer;
 
}

As you can see, in this example the Bidirectional Many to One annotation is explicit also in the target Entity Class.

We can persist and fetch data with this simple Stateless Bean:

@Stateless

public class ServiceBean {

    @PersistenceContext
    private EntityManager em;

    public String create() {
        Customer customer = new Customer();
        customer.setAddress("15th Avenue New York");
        customer.setName("John Smith");
        customer.setPhoneNumber("328/1145678");
        customer.setEmail("[email protected]");

        Request request = new Request();
        request.setCustomer(customer);
        request.setQuantity(125);

        List<Request> list = new ArrayList();
        list.add(request);

        customer.setRequests(list);
        em.persist(customer);

        return "Created!";
    }

    public List<Request> findAll() {

        Query query = em.createQuery("FROM Request");
        List<Request> list = query.getResultList();
        return list;

    }

}

In order to use the default H2 Database, we will include in the persistence.xml a reference to the ExampleDS Datasource:

<persistence-unit name="primary">
        <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
        <properties>
            <!-- Properties for Hibernate -->
            <property name="hibernate.hbm2ddl.auto" value="create-drop" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
</persistence-unit>

AnnotationException: @Column(s) not allowed on a @ManyToOne property

This error can happen if you use @JoinColumn and @Column annotation together.

@ManyToOne
@Column(name="CustomerFK")
private Customer customer;

It will return the following error:

org.hibernate.AnnotationException: @Column(s) not allowed on a @ManyToOne property

You can apply the JPA @Column annotation only for basic entity attributes (e.g. String, Integer, Date) if the entity attribute name differs from the underlying column name.

In the above example, you should rather use the @JoinColumn annotation:

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="CustomerFK")
private Customer customer;

The @JoinColumn annotation allows to customize a Foreign Key column name, and it can only be used with an entity association.

Source code for this tutorial is available here: https://github.com/fmarchioni/mastertheboss/tree/master/hibernate/OneToMany

Found the article helpful? if so please follow us on Socials