hibernate注释映射
Today we will look into One To Many Mapping in Hibernate. We will look into Hibernate One To Many Mapping example using Annotation and XML configuration.
今天,我们将研究Hibernate中的一对多映射。 我们将研究使用注释和XML配置的Hibernate一对多映射示例。
Hibernate中的一对多映射 (One To Many Mapping in Hibernate)
In simple terms, one to many mapping means that one row in a table can be mapped to multiple rows in another table. For example, think of a Cart system where we have another table for Items. A cart can have multiple items, so here we have one to many mapping. We will use Cart-Items scenario for our hibernate one to many mapping example.
简单来说,一对多映射意味着表中的一行可以映射到另一表中的多行。 例如,考虑一个Cart系统,其中有另一个Items表。 一个购物车可以有多个商品,因此这里有一对多映射。 我们将在Hibernate的一对多映射示例中使用Cart-Items场景。
Hibernate中的一对多映射–数据库设置 (One To Many Mapping in Hibernate – Database Setup)
We can use foreign key constraint for one to many mapping. Below is our database script for Cart
and Items
table. I am using MySQL database for Hibernate one to many mapping example.
我们可以将外键约束用于一对多映射。 以下是我们用于Cart
和Items
表的数据库脚本。 我正在将MySQL数据库用于Hibernate一对多映射示例。
setup.sql
setup.sql
CREATE TABLE `Cart` (
`cart_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`total` decimal(10,0) NOT NULL,
`name` varchar(10) DEFAULT NULL,
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,
`item_id` varchar(10) NOT NULL,
`item_total` decimal(10,0) NOT NULL,
`quantity` int(3) 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;
Below is the ER diagram of the Cart and Items table.
下面是购物车和物品表的ER图。
Our database setup is ready, let’s move on to creating hibernate One to Many Mapping example project. First of all, we will use XML based configuration and then we will implement one to many mapping using Hibernate and JPA annotation.
我们的数据库设置已准备就绪,让我们继续创建Hibernate的“一对多映射”示例项目。 首先,我们将使用基于XML的配置,然后使用Hibernate和JPA批注实现一对多映射。
Hibernate一对多映射项目结构 (Hibernate One To Many Mapping Project Structure)
Create a simple Maven project in Eclipse or you favorite IDE, the final project structure will look like below image.
在Eclipse或您喜欢的IDE中创建一个简单的Maven项目,最终的项目结构如下图所示。
HibernateMaven依赖关系 (Hibernate Maven Dependencies)
Our final pom.xml file contains dependencies for Hibernate and MySQL driver. Hibernate uses JBoss logging and it automatically gets added as transitive dependencies.
我们最终的pom.xml文件包含Hibernate和MySQL驱动程序的依赖项。 Hibernate使用JBoss日志记录,它会自动作为传递依赖项添加。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.hibernate</groupId>
<artifactId>HibernateOneToManyMapping</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
</dependencies>
</project>
Note that I am using latest Hibernate version 4.3.5.Final and MySQL driver version based on my database installation.
请注意,我正在使用最新的Hibernate版本4.3.5.Final和MySQL驱动程序版本基于我的数据库安装。
Hibernate一对多映射模型类 (Hibernate One To Many Mapping Model Classes)
For our tables Cart and Items, we have model classes to reflect them.
对于我们的表Cart和Items,我们有模型类来反映它们。
Cart.java
Cart.java
package com.journaldev.hibernate.model;
import java.util.Set;
public class Cart {
private long id;
private double total;
private String name;
private Set<Items> items;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Items> getItems() {
return items;
}
public void setItems(Set<Items> items) {
this.items = items;
}
}
I am using Set of Items, so that every record is unique. We can also use List or Array for one to many mapping in hibernate.
我正在使用项目集,以便每个记录都是唯一的。 我们也可以在Hibernate中使用List或Array进行一对多映射。
Items.java
Items.java
package com.journaldev.hibernate.model;
public class Items {
private long id;
private String itemId;
private double itemTotal;
private int quantity;
private Cart cart;
//Hibernate requires no-args constructor
public Items(){}
public Items(String itemId, double total, int qty, Cart c){
this.itemId=itemId;
this.itemTotal=total;
this.quantity=qty;
this.cart=c;
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public double getItemTotal() {
return itemTotal;
}
public void setItemTotal(double itemTotal) {
this.itemTotal = itemTotal;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Cart getCart() {
return cart;
}
public void setCart(Cart cart) {
this.cart = cart;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
Items have many to one relationship to Cart, so we don’t need to have Collection for Cart object.
项目与购物车有多对一的关系,因此我们不需要为购物车对象设置Collection。
Hibernate SessionFactory实用程序类 (Hibernate SessionFactory Utility Class)
We have a utility class for creating Hibernate SessionFactory.
我们有一个用于创建Hibernate SessionFactory的实用程序类。
HibernateUtil.java
HibernateUtil.java
package com.journaldev.hibernate.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
System.out.println("Hibernate Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
System.out.println("Hibernate serviceRegistry created");
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
if(sessionFactory == null) sessionFactory = buildSessionFactory();
return sessionFactory;
}
}
Hibernate配置XML文件 (Hibernate Configuration XML File)
Our hibernate configuration xml file contains database information and mapping resource details.
我们的Hibernate配置xml文件包含数据库信息和映射资源详细信息。
hibernate.cfg.xml
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"https://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">pankaj123</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">pankaj</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="cart.hbm.xml"/>
<mapping resource="items.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Hibernate一对多映射示例– XML配置 (Hibernate One To Many Mapping Example – XML Configuration)
This is the most important part of tutorial, let’s see how we have to map both Cart and Items classes for one to many mapping in hibernate.
这是教程中最重要的部分,让我们看看如何在冬眠中同时映射Cart和Items类以进行一对多映射。
cart.hbm.xml
cart.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.journaldev.hibernate.model">
<class name="Cart" table="CART" >
<id name="id" type="long">
<column name="cart_id" />
<generator class="identity" />
</id>
<property name="total" type="double">
<column name="total" />
</property>
<property name="name" type="string">
<column name="name" />
</property>
<set name="items" table="ITEMS" fetch="select">
<key>
<column name="cart_id" not-null="true"></column>
</key>
<one-to-many class="Items"/>
</set>
</class>
</hibernate-mapping>
The important part is the set
element and one-to-many
element inside it. Notice that we are providing key to be used for one to many mapping i.e cart_id.
重要的是set
元素和one-to-many
元素。 注意,我们提供了用于一对多映射的密钥,即cart_id。
items.hbm.xml
items.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.journaldev.hibernate.model">
<class name="Items" table="ITEMS">
<id name="id" type="long">
<column name="id" />
<generator class="identity" />
</id>
<property name="itemId" type="string">
<column name="item_id"></column>
</property>
<property name="itemTotal" type="double">
<column name="item_total"></column>
</property>
<property name="quantity" type="integer">
<column name="quantity"></column>
</property>
<many-to-one name="cart" class="Cart">
<column name="cart_id" not-null="true"></column>
</many-to-one>
</class>
</hibernate-mapping>
Notice that from items to cart, it’s many to one relationship. So we need to use many-to-one
element for cart and we are providing column name that will be mapped with the key. So based on the Cart hibernate mapping configuration, it’s key cart_id will be used for mapping.
注意,从物品到购物车,这是多对一的关系。 因此,我们需要对购物车使用many-to-one
元素,并提供将与键映射的列名。 因此,基于CartHibernate映射配置,将使用键cart_id进行映射。
Our project for Hibernate One To Many Mapping Example using XML mapping is ready, let’s write a test program and check if it’s working fine or not.
我们的使用XML映射的Hibernate一对多映射示例项目已经准备就绪,让我们编写一个测试程序,并检查其运行是否正常。
Hibernate一对多映射示例–测试程序 (Hibernate One To Many Mapping Example – Test Program)
HibernateOneToManyMain.java
HibernateOneToManyMain.java
package com.journaldev.hibernate.main;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Cart;
import com.journaldev.hibernate.model.Items;
import com.journaldev.hibernate.util.HibernateUtil;
public class HibernateOneToManyMain {
public static void main(String[] args) {
Cart cart = new Cart();
cart.setName("MyCart");
Items item1 = new Items("I1", 10, 1, cart);
Items item2 = new Items("I2", 20, 2, cart);
Set<Items> itemsSet = new HashSet<Items>();
itemsSet.add(item1); itemsSet.add(item2);
cart.setItems(itemsSet);
cart.setTotal(10*1 + 20*2);
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try{
//Get Session
sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created");
//start transaction
tx = session.beginTransaction();
//Save the Model objects
session.save(cart);
session.save(item1);
session.save(item2);
//Commit transaction
tx.commit();
System.out.println("Cart ID="+cart.getId());
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}finally{
if(!sessionFactory.isClosed()){
System.out.println("Closing SessionFactory");
sessionFactory.close();
}
}
}
}
Notice that we need to save both Cart and Items objects one by one. Hibernate will take care of updating the foreign keys in Items table. When we execute above program, we get following output.
注意,我们需要一个一个地保存Cart和Items对象。 Hibernate将负责更新Items表中的外键。 当我们执行上面的程序时,我们得到以下输出。
Hibernate Configuration loaded
Hibernate serviceRegistry created
Session created
Hibernate: insert into CART (total, name) values (?, ?)
Hibernate: insert into ITEMS (item_id, item_total, quantity, cart_id) values (?, ?, ?, ?)
Hibernate: insert into ITEMS (item_id, item_total, quantity, cart_id) values (?, ?, ?, ?)
Hibernate: update ITEMS set cart_id=? where id=?
Hibernate: update ITEMS set cart_id=? where id=?
Cart ID=6
Closing SessionFactory
Notice that Hibernate is using Update query to set the cart_id in ITEMS table.
注意,Hibernate正在使用Update查询在ITEMS表中设置cart_id。
Hibernate一对多映射注释 (Hibernate One To Many Mapping Annotation)
Now that we have seen how to implement One To Many mapping in Hibernate using XML based configurations, let’s see how we can do the same thing using JPA annotations.
现在,我们已经了解了如何使用基于XML的配置在Hibernate中实现一对多映射,让我们看看如何使用JPA批注来做同样的事情。
Hibernate一对多映射示例注释 (Hibernate One To Many Mapping Example Annotation)
Hibernate configuration file is almost same, except that mapping element changes because we are using Classes for hibernate one to many mapping using annotation.
Hibernate配置文件几乎相同,不同之处在于映射元素发生了变化,因为我们使用Classes通过注释将Hibernate一对多映射到Hibernate。
hibernate-annotation.cfg.xml
hibernate-annotation.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"https://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">pankaj123</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">pankaj</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.journaldev.hibernate.model.Cart1"/>
<mapping class="com.journaldev.hibernate.model.Items1"/>
</session-factory>
</hibernate-configuration>
Hibernate SessionFactory实用程序类 (Hibernate SessionFactory Utility Class)
SessionFactory utility class is almost same, we just need to use the new hibernate configuration file.
SessionFactory实用程序类几乎相同,我们只需要使用新的Hibernate配置文件即可。
HibernateAnnotationUtil.java
HibernateAnnotationUtil.java
package com.journaldev.hibernate.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateAnnotationUtil {
private static SessionFactory sessionFactory;
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate-annotation.cfg.xml
Configuration configuration = new Configuration();
configuration.configure("hibernate-annotation.cfg.xml");
System.out.println("Hibernate Annotation Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
System.out.println("Hibernate Annotation serviceRegistry created");
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
if(sessionFactory == null) sessionFactory = buildSessionFactory();
return sessionFactory;
}
}
Hibernate一对多映射注释模型类 (Hibernate One To Many Mapping Annotation Model Classes)
Since we don’t have xml based mapping files, all the mapping related configurations will be done using JPA annotations in the model classes. If you understand the xml based mapping, it’s very simple and similar.
由于我们没有基于xml的映射文件,因此所有与映射相关的配置都将使用模型类中的JPA注释来完成。 如果您了解基于xml的映射,那么它非常简单且相似。
Cart1.java
Cart1.java
package com.journaldev.hibernate.model;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="CART")
public class Cart1 {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="cart_id")
private long id;
@Column(name="total")
private double total;
@Column(name="name")
private String name;
@OneToMany(mappedBy="cart1")
private Set<Items1> items1;
// Getter Setter methods for properties
}
Important point to note is the OneToMany
annotation where mappedBy
variable is used to define the property in Items1
class that will be used for the mapping purpose. So we should have a property named “cart1” in Items1 class. Don’t forget to include all the getter-setter methods.
需要注意的重要一点是OneToMany
批注,其中mappedBy
变量用于定义Items1
类中的属性,该属性将用于映射目的。 因此,我们应该在Items1类中有一个名为“ cart1”的属性。 不要忘记包括所有的getter-setter方法。
Items1.java
Items1.java
package com.journaldev.hibernate.model;
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.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="ITEMS")
public class Items1 {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private long id;
@Column(name="item_id")
private String itemId;
@Column(name="item_total")
private double itemTotal;
@Column(name="quantity")
private int quantity;
@ManyToOne
@JoinColumn(name="cart_id", nullable=false)
private Cart1 cart1;
//Hibernate requires no-args constructor
public Items1(){}
public Items1(String itemId, double total, int qty, Cart1 c){
this.itemId=itemId;
this.itemTotal=total;
this.quantity=qty;
this.cart1=c;
}
//Getter Setter methods
}
Most important point in above class is the ManyToOne
annotation on Cart1 class variable and JoinColumn
annotation to provide the column name for mapping.
上一类中最重要的一点是Cart1类变量上的ManyToOne
批注和JoinColumn
批注,以提供用于映射的列名。
That’s it for one to many mapping in hibernate using annotation in model classes. Compare it with XML based configurations, you will find them very similar.
在Hibernate中使用模型类中的注释进行一对多映射就可以了。 将其与基于XML的配置进行比较,您会发现它们非常相似。
Let’s write a test program and execute it.
让我们编写一个测试程序并执行它。
Hibernate一对多映射注释示例测试程序 (Hibernate One To Many Mapping Annotation Example Test Program)
Our test program is just like xml based configuration, we are just using the new classes for getting Hibernate Session and saving the model objects into database.
我们的测试程序就像基于xml的配置一样,我们只是使用新类来获取Hibernate Session并将模型对象保存到数据库中。
HibernateOneToManyAnnotationMain.java
HibernateOneToManyAnnotationMain.java
package com.journaldev.hibernate.main;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Cart1;
import com.journaldev.hibernate.model.Items1;
import com.journaldev.hibernate.util.HibernateAnnotationUtil;
public class HibernateOneToManyAnnotationMain {
public static void main(String[] args) {
Cart1 cart = new Cart1();
cart.setName("MyCart1");
Items1 item1 = new Items1("I10", 10, 1, cart);
Items1 item2 = new Items1("I20", 20, 2, cart);
Set<Items1> itemsSet = new HashSet<Items1>();
itemsSet.add(item1); itemsSet.add(item2);
cart.setItems1(itemsSet);
cart.setTotal(10*1 + 20*2);
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try{
//Get Session
sessionFactory = HibernateAnnotationUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created");
//start transaction
tx = session.beginTransaction();
//Save the Model object
session.save(cart);
session.save(item1);
session.save(item2);
//Commit transaction
tx.commit();
System.out.println("Cart1 ID="+cart.getId());
System.out.println("item1 ID="+item1.getId()+", Foreign Key Cart ID="+item1.getCart1().getId());
System.out.println("item2 ID="+item2.getId()+", Foreign Key Cart ID="+item1.getCart1().getId());
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}finally{
if(!sessionFactory.isClosed()){
System.out.println("Closing SessionFactory");
sessionFactory.close();
}
}
}
}
When we execute above hibernate one to many mapping annotation example test program, we get following output.
当我们在Hibernate状态下执行一对多映射注释示例测试程序时,将得到以下输出。
Hibernate Annotation Configuration loaded
Hibernate Annotation serviceRegistry created
Session created
Hibernate: insert into CART (name, total) values (?, ?)
Hibernate: insert into ITEMS (cart_id, item_id, item_total, quantity) values (?, ?, ?, ?)
Hibernate: insert into ITEMS (cart_id, item_id, item_total, quantity) values (?, ?, ?, ?)
Cart1 ID=7
item1 ID=9, Foreign Key Cart ID=7
item2 ID=10, Foreign Key Cart ID=7
Closing SessionFactory
That’s all for hibernate one to many mapping, download the sample project from below link and do some more experiments.
这就是Hibernate一对多映射,从下面的链接下载示例项目并进行更多实验的全部内容。
翻译自: https://www.journaldev.com/2924/hibernate-one-to-many-mapping-annotation
hibernate注释映射