无法使用休眠将引用键存储在表中

Posted

技术标签:

【中文标题】无法使用休眠将引用键存储在表中【英文标题】:Unable to store referencing key in the table using hibernate 【发布时间】:2021-11-08 22:03:18 【问题描述】:

我正在尝试将客户详细信息(ID、名字和姓氏)保存在客户表中,并将客户订单(ID 和订单号)保存在订单表中。

当使用休眠将这些详细信息存储在 mysql 数据库中时,它应该将引用键(客户 ID)存储在订单表中,因为客户和订单具有一对多的关系。

但是当我在数据库中获取数据时,orders 表中的客户 id 列具有 NULL 值。为什么我无法在该列中存储客户 ID?

Customer.java

@Entity
public class Customer 
    @Id
    @Column(name = "id")
    private Integer id;
    
    private Name name;

    @OneToMany(mappedBy = "customer")
    private List<Order> orders;
    
    public Customer() 
    
    

    public Customer(Integer id, Name name) 
        this.id = id;
        this.name = name;
    

    public Customer(Integer id, Name name, List<Order> orders) 
        this.id = id;
        this.name = name;
        this.orders = orders;
    


    public Integer getId() 
        return id;
    

    public void setId(Integer id) 
        this.id = id;
    
    
    public Name getName() 
        return name;
    

    public void setName(Name name) 
        this.name = name;
    

    public List<Order> getOrders() 
        return orders;
    
    
    
    public void setOrders(List<Order> orders) 
        this.orders = orders;
    

    @Override
    public String toString() 
        return "Customer [id=" + id + ", name=" + name + ", orders=" + orders + "]";
    

Name.java

@Embeddable
public class Name 
    @Column(name = "first_name")
    private String firstName;

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

    public Name() 
    

    public Name(String firstName, String lastName) 
        this.firstName = firstName;
        this.lastName = lastName;
    

    public String getFirstName() 
        return firstName;
    

    public void setFirstName(String firstName) 
        this.firstName = firstName;
    

    public String getLastName() 
        return lastName;
    

    public void setLastName(String lastName) 
        this.lastName = lastName;
    

    @Override
    public String toString() 
        return "Name [firstName=" + firstName + ", lastName=" + lastName + "]";
    

 

Order.java

@Entity
@Table(name = "Orders")
public class Order 
    @Id
    @Column(name = "Id")
    private Integer id;
    
    @Column(name = "OrderNumber")
    private String orderNumber;
    
    @ManyToOne
    private Customer customer;

    public Order() 
        
    
    
    public Order(Integer id, String orderNumber) 
        this.id = id;
        this.orderNumber = orderNumber;
    

    public Order(Integer id, String orderNumber, Customer customer) 
        this.id = id;
        this.orderNumber = orderNumber;
        this.customer = customer;
    

    public Integer getId() 
        return id;
    

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

    public String getOrderNumber() 
        return orderNumber;
    

    public void setOrderNumber(String orderNumber) 
        this.orderNumber = orderNumber;
    

    public Customer getCustomer() 
        return customer;
    

    public void setCustomer(Customer customer) 
        this.customer = customer;
    

    @Override
    public String toString() 
        return "Order [id=" + id + ", orderNumber=" + orderNumber + ", customer=" + customer + "]";
    

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!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>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/ecomtest</property>
        <property name="hibernate.connection.username">username</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
        <property name="hbm2ddl.auto">update</property>
        <property name="show_sql">true</property>
    </session-factory>
</hibernate-configuration>

App.java

public class App 

    public static void main(String[] args) 
        
        List<Order> orders = new ArrayList<>();
        orders.add(new Order(101, "A124B"));
        orders.add(new Order(102, "A124C"));
        Customer c1 = new Customer(1, new Name("Hardik", "Jain"), orders);
        
        Configuration con = new Configuration().configure().addAnnotatedClass(Customer.class).addAnnotatedClass(Order.class);
        
        SessionFactory sessionFactory = con.buildSessionFactory();
        Session session = sessionFactory.openSession();
        
        Transaction t = session.beginTransaction();
        session.save(c1);
        for(Order order: orders) 
            session.save(order);
        
        t.commit();
    


客户表

id first_name  last_name 
1   Hardik      Jain     

订单表

Id  OrderNumber customer_id
101   A124B       NULL  
102   A124C       NULL 

【问题讨论】:

【参考方案1】:

以下更改解决了该问题:

为每个 Order 对象设置客户 为客户对象 (c1) 设置订单
public class App 

    public static void main(String[] args) 
        
        List<Order> orders = new ArrayList<>();
        Customer c1 = new Customer(1, new Name("Hardik", "Jain"));
        orders.add(new Order(101, "A124B", c1)); // set customer
        orders.add(new Order(102, "A124C", c1)); // set customer
        
        c1.setOrders(orders) // separately setting orders

        Configuration con = new Configuration().configure()
                 .addAnnotatedClass(Customer.class)
                 .addAnnotatedClass(Order.class);
        
        SessionFactory sessionFactory = con.buildSessionFactory();
        Session session = sessionFactory.openSession();
        
        Transaction t = session.beginTransaction();
        session.save(c1);
        for(Order order: orders) 
            session.save(order);
        
        t.commit();
    


【讨论】:

以上是关于无法使用休眠将引用键存储在表中的主要内容,如果未能解决你的问题,请参考以下文章

Vue(Laravel 8)无法正确呈现存储在表中的数组

无法使用oracle中的游标在表中插入记录

提交值后无法在表中获取值

访问 2007 引用完整性而不使用表中的查找

使用 C# 出现错误“无法在表中插入标识列的显式值”

在表中显示来自本地数据的信息