Home > Software engineering >  Why is Hibernate not creating many-to-many join tables?
Why is Hibernate not creating many-to-many join tables?

Time:12-20

I am trying to get Hibernate to create a many-to-many relationship join table. The entity tables are created just fine, but the join table won't show up. Some source create the join table by hand, others, like Youtube Tutorials explain how they are created automatically by Hibernate.

Here is my first Entity table:

package com.presents;
import javax.persistence.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.Set;

 @Entity
 @Table(name = "articles")
 public class Article implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;

@Column(name = "name")
private String name;

@Column(name = "link")
private String url;

@Column(name = "likes")
private int likes;

@Column(name = "clicks")
private int clicks;

@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
        name = "category_article",
        joinColumns = {
                @JoinColumn(name = "article_id", referencedColumnName = "id")
        },
        inverseJoinColumns =  {
                @JoinColumn(name = "category_id", referencedColumnName = "id")
        }
)
public Set<Categories> categories = new HashSet<>();;


public int getId() {
    return id;
}

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

public String getName() {
    return name;
}

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

public String getUrl() {
    return url;
}

public void setUrl(String url) {
    this.url = url;
}

public int getLikes() {
    return likes;
}

public void setLikes(int likes) {
    this.likes = likes;
}

public int getClicks() {
    return clicks;
}

public void setClicks(int clicks) {
    this.clicks = clicks;
}

public Set<Categories> getCategories() {
    return cats;
}

public void setCategories(Set<Categories> categories) {
    this.cats = categories;
}

}

This is my second Entity table:

package com.presents;

import javax.persistence.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "category")
public class Categories implements Serializable {

@Serial
private static final long serialVersionUID = 1L;


@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "id")
private int id;

@Column(name = "category")
private String category;

@ManyToMany(mappedBy = "categories")
public Set<Article> articles = new HashSet<>();

public Integer getId() {
    return id;
}

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

public void setCategory(String category) {
    this.category = category;
}

public String getCategory() {
    return category;
}

public void setArticles(Set<Article> articles) {
    this.articles = articles;
}

public Set<Article> getArticles() {
    return articles;
}

}

The idea is that any article can be in many categories, but more than one category can apply to any article.

I am using a SQLite3 database, but I tried also with a MySQL database, both to no avail. Hibernate seems somehow to avoid the many-to-many annotation completely. It does not complain about it when I ran the code and seems to avoid it altogether. Again, the other to tables are created beautifully, without me fumbling around with any SQL commands. Why is Hibernate refusing to create the join table, and how do I fix it?

Here is the output of Hibernate:

INFO: HHH000412: Hibernate ORM core version 5.6.2.Final
Dez. 18, 2021 8:41:14 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
Dez. 18, 2021 8:41:15 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Dez. 18, 2021 8:41:15 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.sqlite.JDBC] at URL [jdbc:sqlite:presents.db]
Dez. 18, 2021 8:41:15 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {}
Dez. 18, 2021 8:41:15 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Dez. 18, 2021 8:41:15 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Dez. 18, 2021 8:41:15 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.SQLiteDialect
Hibernate: drop table if exists articles
Hibernate: drop table if exists category
Hibernate: drop table if exists hibernate_sequence
Hibernate: create table articles (id integer not null, name varchar, link varchar, likes integer, clicks integer, primary key (id))
Hibernate: create table category (id integer not null, category varchar, primary key (id))
Hibernate: create table hibernate_sequence (next_val bigint)
Hibernate: insert into hibernate_sequence values ( 1 )
Dez. 18, 2021 8:41:16 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@334ebcaa] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Dez. 18, 2021 8:41:16 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@107bfcb2] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Dez. 18, 2021 8:41:16 AM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: insert into articles (name, link, likes, clicks, id) values (?, ?, ?, ?, ?)
Hibernate: insert into articles (name, link, likes, clicks, id) values (?, ?, ?, ?, ?)
Hibernate: insert into articles (name, link, likes, clicks, id) values (?, ?, ?, ?, ?)
Hibernate: insert into articles (name, link, likes, clicks, id) values (?, ?, ?, ?, ?)
Hibernate: insert into category (category, id) values (?, ?)
Hibernate: insert into category (category, id) values (?, ?)
Hibernate: insert into category (category, id) values (?, ?)
Hibernate: select categories0_.id as id1_1_, categories0_.category as category2_1_ from category categories0_

CodePudding user response:

You need to get an article, then add a category and save it. For example:

Categories category = categoryRepository.getById(100001);
article.getCategories().add(category);
articlesRepository.save(article);
productRepository.findAll();

This will add a new entry to the category_article table.

CodePudding user response:

I found the mistake myself. I was using JPA annotations when I should have used Hibernate XML mapping. After removing every annotation and creating the necessary lines in the XML mapping files, the table appeared.

  • Related