Le champ 'index_id' n'a pas de valeur par défaut "lorsque vous essayez d'utiliser la clé primaire dans le cadre de la clé composite dans Hibernate

2020-06-01 java mysql hibernate

J'utilise Hibernate pour mettre à jour les données de la base de données MySQL. J'ai deux tables index et propriétés comme décrit ci-dessous.

L'index_id dans la première table n'est pas généré automatiquement et j'assigne la valeur.

Lorsque j'essaye de faire index_id dans le cadre de la clé composite dans la table des propriétés, j'obtiens "Le champ 'index_id' n'a pas de valeur par défaut". Je peux insérer les données manuellement dans MySQL mais mon problème est que je ne peux pas le faire via le code Hibernate.

CREATE TABLE index (
    index_id BINARY(16),
    index_name VARCHAR(225) NOT NULL ,
    config VARCHAR(255) NOT NULL,

    PRIMARY KEY (index_id)
);

CREATE TABLE properties (
    index_id BINARY(16),
    property_key VARCHAR(225) NOT NULL,
    property_value VARCHAR(225) NOT NULL,

    PRIMARY KEY (index_id, property_key),
    FOREIGN KEY (index_id) REFERENCES index(index_id)  
);

Classes correspondantes pour les mêmes avec des annotations Hibernate.

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import java.util.Date;
import java.util.Set;
import java.util.UUID;

import com.sun.istack.NotNull;

@Entity
@Table(name = "index")
public class Index {
    @Id
    @Column(name = "index_id")
    private UUID indexId;

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

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

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "index_id")
    private Set<Property> properties;

    public Index() {}
}

Les réponses suggérées dans d'autres articles utilisent une valeur générée automatiquement, ce qui n'est pas ce que je recherche.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "properties")
public class Property implements Serializable {
    private static final long serialVersionUID = 1881413500711441951L;

    @Id
    @Column(name = "property_key")
    private String propertyKey;

    @Id
    @Column(name = "property_value")
    private String propertyValue;

    public Property() {}

    public Property(String propertyKey, String propertyValue) {
        this.propertyKey = propertyKey;
        this.propertyValue = propertyValue;
    }
}

hibernate.cfg.xml

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name = "hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- JDBC Database connection settings -->
        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/index?useSSL=false</property>
        <property name="connection.username">###</property>
        <property name="connection.password">###</property>
        <!-- JDBC connection pool settings ... using built-in test pool -->
        <property name="connection.pool_size">1</property>
        <!-- Select our SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <!-- Echo the SQL to stdout -->
        <property name="show_sql">true</property>
        <!-- Set the current session context -->
        <property name="current_session_context_class">thread</property>
        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>
        <!-- dbcp connection pool configuration -->
        <mapping class="com.learning.models.Index" />
        <mapping class="com.learning.models.Property" />
    </session-factory>
</hibernate-configuration>

HibernateUtil.java

import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class HibernateUtil {
    private static StandardServiceRegistry registry;
    private static SessionFactory sessionFactory;
    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                // Create registry
                registry = new StandardServiceRegistryBuilder().configure().build();
                // Create MetadataSources
                MetadataSources sources = new MetadataSources(registry);
                // Create Metadata
                Metadata metadata = sources.getMetadataBuilder().build();
                // Create SessionFactory
                sessionFactory = metadata.getSessionFactoryBuilder().build();
            } catch (Exception e) {
                e.printStackTrace();
                if (registry != null) {
                    StandardServiceRegistryBuilder.destroy(registry);
                }
            }
        }
        return sessionFactory;
    }
    public static void shutdown() {
        if (registry != null) {
            StandardServiceRegistryBuilder.destroy(registry);
        }
    }
}

Answers

J'ai pu résoudre le problème. J'avais une relation un à plusieurs comme indiqué dans la classe Index

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "index_id")
private Set<Property> properties;

Le problème était que je dois faire un mappage plusieurs à un dans la classe des propriétés avec l'index_id.

J'ai changé la classe Propriétés comme ci-dessous.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "properties")
public class Property implements Serializable {
    private static final long serialVersionUID = 1881413500711441951L;

    @Id
    @Column(name = "property_key")
    private String propertyKey;

    @Id
    @Column(name = "property_value")
    private String propertyValue;

    @Id
    @ManyToOne
    @JoinColumn(name ="index_id")
    private Index index;

    public Property() {}

    public Property(String propertyKey, String propertyValue, Index index) {
        this.propertyKey = propertyKey;
        this.propertyValue = propertyValue;
        this.index = index;
    }
}

Related