Hibernate 休眠关系(一对多、多对多、一对一)

Hibernate 休眠关系(一对多、多对多、一对一),hibernate,Hibernate,我正在做一个项目,希望在其中实现Hibernate。我看过很多讨论关系的视频,给出了一些例子,比如客户订单,其中一个客户可以有很多订单,但订单只涉及一个客户。或者,学生可以参加许多课程,反之亦然。在我的特殊情况下,我有一个客户表和一个问候表,我希望确保使用一套标准的问候语,因此我有以下内容: 我不知道如何建立这种关系。在我看到的所有示例中,您都会在Customer表中放置对称呼对象的引用,但这似乎没有意义。下面“我的客户”表中的称呼字段的类型为int。那么如何为此类实例建立关系呢?谢谢你的帮助

我正在做一个项目,希望在其中实现Hibernate。我看过很多讨论关系的视频,给出了一些例子,比如客户订单,其中一个客户可以有很多订单,但订单只涉及一个客户。或者,学生可以参加许多课程,反之亦然。在我的特殊情况下,我有一个客户表和一个问候表,我希望确保使用一套标准的问候语,因此我有以下内容:


我不知道如何建立这种关系。在我看到的所有示例中,您都会在Customer表中放置对称呼对象的引用,但这似乎没有意义。下面“我的客户”表中的称呼字段的类型为int。那么如何为此类实例建立关系呢?谢谢你的帮助

我认为你必须了解各种各样的关系

使用的关系图在另一个实体内显示外部化的关系图。你可以这么做,但没有什么强迫你这么做。大多数情况下进展顺利。自由

在我的特殊情况下,我有一个客户表和一个问候表,在这里我想确定一组标准的问候语

你写的那篇文章告诉我你有一个客户和许多可能的称呼。如果Web用户只能选择其中一个,那么您的图表就很好

否则,如果Web用户可以选择其中许多,那么您必须查看一个

也存在,但您不在该用例中


您可以从首选关系数据库的官方文档中学习。但是需要理解的基础知识在SQL教程中。我喜欢这些或一个的。

正如你所说,你正在学习,除了
hibernate
spring
spring boot
之外,没有标记任何其他标记,让我详细介绍一下,让你完成工作

让我们以
购物车和物品
表格为例。我们对一对多映射使用外键约束:

CREATE TABLE `Cart` (
  `cart_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`cart_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
 
CREATE TABLE `Items` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `cart_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `cart_id` (`cart_id`),
  CONSTRAINT `items_ibfk_1` FOREIGN KEY (`cart_id`) REFERENCES `Cart` (`cart_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
如果您使用的是springboot,那么您可以跳过配置步骤,因为它只预先配置了一个依赖项

Maven依赖关系

private static SessionFactory sessionFactory;
 
private SessionFactory buildSessionFactory() {
      
    ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().
      configure("hibernate-annotation.cfg.xml").build();
    Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();
    SessionFactory sessionFactory = metadata.getSessionFactoryBuilder().build();
             
    return sessionFactory;
}   
 
public SessionFactory getSessionFactory() {
    if(sessionFactory == null) sessionFactory = buildSessionFactory();
    return sessionFactory;
}
然后,我们将Hibernate和H2驱动程序依赖项添加到pom.xml文件中。Hibernate依赖项使用JBoss日志记录,并自动添加为可传递依赖项:

  • Hibernate版本5.2.7.Final
  • H2驱动程序版本1.4.197
有关Hibernate和H2依赖项的最新版本,请访问Maven中央存储库

休眠配置

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        <property name="hibernate.connection.password"></property>
        <property name="hibernate.connection.url">
          jdbc:h2:mem:spring_hibernate_one_to_many</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.show_sql">true</property>
    </session-factory>
</hibernate-configuration>
模型

private static SessionFactory sessionFactory;
 
private SessionFactory buildSessionFactory() {
      
    ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().
      configure("hibernate-annotation.cfg.xml").build();
    Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();
    SessionFactory sessionFactory = metadata.getSessionFactoryBuilder().build();
             
    return sessionFactory;
}   
 
public SessionFactory getSessionFactory() {
    if(sessionFactory == null) sessionFactory = buildSessionFactory();
    return sessionFactory;
}
映射相关配置将使用模型类中的JPA注释完成:

@Entity
@Table(name="CART")
public class Cart {
 
    //...
 
    @OneToMany(mappedBy="cart")
    private Set<Items> items;
     
    // getters and setters
}
在行动中

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        <property name="hibernate.connection.password"></property>
        <property name="hibernate.connection.url">
          jdbc:h2:mem:spring_hibernate_one_to_many</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.show_sql">true</property>
    </session-factory>
</hibernate-configuration>
在测试程序中,我们使用main()方法创建一个类,用于获取Hibernate会话,并将模型对象保存到实现一对多关联的数据库中:

sessionFactory = HibernateAnnotationUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created");
         
tx = session.beginTransaction();
 
session.save(cart);
session.save(item1);
session.save(item2);
         
tx.commit();
System.out.println("Cart ID=" + cart.getId());
System.out.println("item1 ID=" + item1.getId()
  + ", Foreign Key Cart ID=" + item.getCart().getId());
System.out.println("item2 ID=" + item2.getId()
+ ", Foreign Key Cart ID=" + item.getCart().getId());
这是我们测试程序的输出:

 Session created    

Hibernate: insert into CART values ()    

Hibernate: insert into ITEMS (cart_id)

  values (?)    

Hibernate: insert into ITEMS (cart_id)    

  values (?)

Cart ID=7


item1 ID=11, Foreign Key Cart ID=7


item2 ID=12, Foreign Key Cart ID=7


Closing SessionFactory
注释
@ManyToOne
注释

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        <property name="hibernate.connection.password"></property>
        <property name="hibernate.connection.url">
          jdbc:h2:mem:spring_hibernate_one_to_many</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.show_sql">true</property>
    </session-factory>
</hibernate-configuration>
如上所述,我们可以使用
@ManyToOne
注释指定
多对一
关系。多对一映射表示此实体的多个实例映射到另一实体的一个实例–一个购物车中的多个项目

@ManyToOne注释也允许我们创建双向关系。我将进一步详细介绍这一点

不一致和所有权

现在,如果购物车引用了商品,但商品并没有反过来引用购物车,我们的关系将是单向的。对象也将具有自然的一致性

然而,在我们的例子中,这种关系是双向的,带来了不一致的可能性

让我们设想这样一种情况:开发人员希望将item1添加到cart,将item2添加到cart2,但却犯了一个错误,因此cart2和item2之间的引用变得不一致:

Cart cart1 = new Cart();
Cart cart2 = new Cart();
 
Items item1 = new Items(cart1);
Items item2 = new Items(cart2); 
Set<Items> itemsSet = new HashSet<Items>();
itemsSet.add(item1);
itemsSet.add(item2); 
cart1.setItems(itemsSet); // wrong!
作为拥有方的购物车

也可以将一对多侧标记为拥有侧,将多对一侧标记为反向侧

虽然这不是推荐的做法,但让我们继续尝试一下

下面的代码片段显示了一对多端作为拥有端的实现:

public class ItemsOIO {
     
    //  ...
    @ManyToOne
    @JoinColumn(name = "cart_id", insertable = false, updatable = false)
    private CartOIO cart;
    //..
}
 
public class CartOIO {
     
    //..  
    @OneToMany
    @JoinColumn(name = "cart_id") // we need to duplicate the physical information
    private Set<ItemsOIO> items;
    //..
}
如上所示,现在item2属于购物车


希望通过学习前瞻性就足够了。

所以,我很抱歉,我的桌子应该更清楚。在customer表中,它应该是saltation_id。因此,它是customer表中的外键,引用saltation表中的主键。在敬礼表中,应该是敬礼,而不仅仅是敬礼。目标是确保客户可以使用一套标准问候语。客户只能选择一个问候语(先生、女士等),然后我会进行连接以提取问候语描述。希望一切都会好起来。请分配赏金先生:)