简体   繁体   中英

Hibernate could not determine type for: java.util.Collection in many to many relation

I am learning manytomany relationship in hibernate from the tutorial. My example project has two tables called product_table and order_table. I was using many to many relationship between these two tables.

While executing my code I found the following error in the console:

Exception in thread "main" org.hibernate.MappingException: Could not determine type for: java.util.Collection, at table: product_details, for columns: [org.hibernate.mapping.Column(orders)]
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:456)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:423)
    at org.hibernate.mapping.Property.isValid(Property.java:226)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:597)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:459)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726)
    at com.hibernatetest.main.MainApp.hibernateSession(MainApp.java:98)
    at com.hibernatetest.main.MainApp.main(MainApp.java:93)

Here's my Hibernate configuration file:

<!-- ~ Hibernate, Relational Persistence for Idiomatic Java ~ ~ License: 
    GNU Lesser General Public License (LGPL), version 2.1 or later. ~ See the 
    lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. -->
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
    <!-- In case of using MySQL greater than 5 use MYSQL5 Dialect in stead of mysqldialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

        <!-- Assume test is the database name -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_test?createDatabaseIfNotExist=true</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password"></property>


        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">create</property>

        <mapping class="com.hibernatetest.dto.ProductDetails" />
        <mapping class="com.hibernatetest.dto.OrderDetails" />


    </session-factory>
</hibernate-configuration>

Here's my OrderDetails classes:

package com.hibernatetest.dto;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "product_details")
public class ProductDetails {

    private int productId;
    private String productName;
    @ManyToMany(mappedBy="product_details")
    private Collection<OrderDetails> orders=new ArrayList();

    public ProductDetails() {
    }

    public ProductDetails(String productName) {
        this.productName = productName;
    }

    @Id
    @Column(name = "product_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getProductId() {
        return productId;
    }

    public void setProductId(int productId) {
        this.productId = productId;
    }

    @Column(name = "product_name")
    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }


    public Collection<OrderDetails> getOrders() {
        return orders;
    }

    public void setOrders(Collection<OrderDetails> orders) {
        this.orders = orders;
    }



}

Here is my OrderDetails class:

package com.hibernatetest.dto;

import java.util.ArrayList;
import java.util.Collection;

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.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "order_details")
public class OrderDetails {

    private int orderId;
    private String orderName;
    @ManyToMany
    private Collection<ProductDetails> products = new ArrayList();

    public OrderDetails() {
        super();
    }

    public OrderDetails(String orderName) {
        super();
        this.orderName = orderName;
    }

    @Id
    @Column(name = "order_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    @Column(name = "order_name")
    public String getOrderName() {
        return orderName;
    }

    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }

    public Collection<ProductDetails> getProduct() {
        return products;
    }

    public void setProduct(Collection<ProductDetails> products) {
        this.products = products;
    }

}

Here is MainApp class:

package com.hibernatetest.main;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.hibernatetest.dto.Address;
import com.hibernatetest.dto.Office;
import com.hibernatetest.dto.OrderDetails;
import com.hibernatetest.dto.ProductDetails;
import com.hibernatetest.dto.UserDetails;

public class MainApp {

    public static void main(String[] args) {
        /*
         * UserDetails user = new UserDetails(); UserDetails user2=new UserDetails();
         * Address address1=new Address("test street1", "test city1", "test state",
         * "0000"); Address address2=new Address("test street2", "test city2",
         * "test state", "0001"); //user.setUserId(2); user.setUsername("Test User 1");
         * user2.setUsername("Test User 2"); user.setJoinedDate(new Date());
         * user2.setJoinedDate(new Date()); user.setHomeAddress(address1);
         * user.setOfficeAddress(address2); user2.setHomeAddress(address2);
         * user2.setOfficeAddress(address1); user.setDescription("test data 1");
         * user2.setDescription("test data 2"); user.setJoinedTime(new Date());
         * user2.setJoinedTime(new Date());
         * 
         * String officePhone1="00000000"; String officePhone2="00000001"; String
         * officePhone3="00000002"; Collection<String> phoneNumbers=new
         * ArrayList<String>(); phoneNumbers.add(officePhone1);
         * phoneNumbers.add(officePhone2); phoneNumbers.add(officePhone3); Office
         * office=new Office(1,"Test Office 1", address1,phoneNumbers);
         * 
         * SessionFactory sessionFactory = new
         * Configuration().configure().buildSessionFactory();
         * 
         * Session session = sessionFactory.openSession();
         * 
         * session.beginTransaction();
         * 
         * session.save(user); session.save(user2); session.save(office);
         * 
         * session.getTransaction().commit();
         * 
         * session.close();
         * 
         * user=null;
         * 
         * session= sessionFactory.openSession(); session.beginTransaction();
         * user=session.get(UserDetails.class,2);
         * 
         * System.out.println(user.getUserId()+" "+user.getDescription());
         * 
         * session.close(); office=null; session=sessionFactory.openSession();
         * session.beginTransaction(); office=session.get(Office.class, 1);
         * System.out.println(office.getOfficeName()); session.close();
         * System.out.println(office.getPhoneList().size());
         */

        ProductDetails product1 = new ProductDetails("Sample product 1");
        ProductDetails product2 = new ProductDetails("Sample product 2");
        ProductDetails product3 = new ProductDetails("Sample product 3");
        ProductDetails product4 = new ProductDetails("Sample product 4");
        OrderDetails order1 = new OrderDetails("Order No 1");
        OrderDetails order2 = new OrderDetails("Order No 2");

        product1.getOrders().add(order1);
        product1.getOrders().add(order2);
        product2.getOrders().add(order2);


        order1.getProduct().add(product1);
        order1.getProduct().add(product2);
        order1.getProduct().add(product3);
        order2.getProduct().add(product1);
        order2.getProduct().add(product3);
        order2.getProduct().add(product4);

        List<Object> insetableObjects = new ArrayList<Object>();
        insetableObjects.add(product1);
        insetableObjects.add(product2);
        insetableObjects.add(product3);
        insetableObjects.add(product4);
        insetableObjects.add(order1);
        insetableObjects.add(order2);
        hibernateSession(insetableObjects);

    }

    public static void hibernateSession(List<Object> collection) {
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

        Session session = sessionFactory.openSession();

        session.beginTransaction();

        for (Object obj : collection) {
            session.save(obj);
            System.out.println("Object Added");
        }

        session.getTransaction().commit();
        session.close();
    }
}

Please guide me to the next steps and thanks in advance.

See this tutorial and Jack Flamp 's comments. In order to establish a ManyToMany relationship, you need a @JoinTable referencing the table you want to use in its specific class, and a reference in the other. For instance, in your case it would be something like:

ProductDetails:

@Entity
@Table(name = "product_details")
public class ProductDetails {

    private int productId;
    private String productName;

    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "order_product", 
        joinColumns = { @JoinColumn(name = "productId") }, 
        inverseJoinColumns = { @JoinColumn(name = "orderId") }
    )
    private Collection<OrderDetails> orders = new ArrayList();

    [...]

OrderDetails:

@Entity
@Table(name = "order_details")
public class OrderDetails {

    private int orderId;
    private String orderName;
    @ManyToMany(mappedBy = "orders")
    private Collection<ProductDetails> products = new ArrayList();

Here, your "owning side" (= the one holding the information) is the product. Your product can have multiple orders, and an order belongs to multiple products. Of course, feel free to revert them as you wish if it does not suit your needs. The link I gave you explains well what each annotation does.


EDIT : Make sure that (in the example) the order_product table actually exists. Otherwise, it won't work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM