今天天气终于放晴了,心情也会好一些。年前这段时间,打算多写点文章,将自己的东西记录下来,算是一种沉淀吧。目前写的东西都是偏基础,也是计划从基础开始写起,后面再慢慢去扩充。
这篇文章打算记录一下Hibernate实现关联关系的操作。上一篇文章介绍了Hibernate的基本使用。
在实际项目开发中,不可能永远都是在一张表上进行操作,比如一本书只有一个作者,但是一个作者可以有多本书,相对于书而言,就是一个多对一的关系。如图:
就以上模型,我们开始Hibernate关联关系中的多对一配置和操作。
一、在MySQL中创建2张表
1、作者表(tb_user),创建表的语句如下:
create table bookmanager.tb_user(
user_id int primary key auto_increment,
user_name varchar(10),
user_password varchar(10),
user_create_time datetime default NOW()
);
2、图书表(tb_book),创建表的语句如下:
CREATE TABLE tb_book (
book_id INT PRIMARY KEY AUTO_INCREMENT,
book_name VARCHAR(45),
book_price INT,
book_author_id int(45),
foreign key(book_author_id) references tb_user(user_id)
);
其中book_author_id是外键,用于关联tb_user表中的主键。接下来在使用hibernate的配置的时候,也会用到此外键。
二、接下来创建2个POJO对象,和上面的2张表相对应。
1、创建一个UserDTO对象,代码如下:
package com.androidxx.hibernatedemo.dto;
import java.sql.Date;
import java.util.Set;
public class UserDTO {
private Long userId;
private String userName;
private String password;
private Date createTime;
public UserDTO() {
super();
// TODO Auto-generated constructor stub
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
2、创建一个Book DTO对象,代码如下(注意代码中包含了UserDTO对象):
package com.androidxx.hibernatedemo.dto;
public class BookDTO {
private Long bookId;
private String bookName;
private Integer bookPrice;
private UserDTO userDto;
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public Integer getBookPrice() {
return bookPrice;
}
public void setBookPrice(Integer bookPrice) {
this.bookPrice = bookPrice;
}
public UserDTO getUserDto() {
return userDto;
}
public void setUserDto(UserDTO userDto) {
this.userDto = userDto;
}
}
以上代码将UserDTO作为了Book DTO的一个属性,这是为了匹配多对一的特性。一个Book对象有一个作者对象User,这在上面的代码中能体现出来。
三、创建hibernate的映射文件
1、UserDTO对应的映射文件user.hbm.xml,其代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.androidxx.hibernatedemo.dto.UserDTO" table="tb_user">
<id name="userId" type="java.lang.Long" column="user_id">
<generator class="identity"/>
</id>
<property name="userName" type="java.lang.String" column="user_name"></property>
<property name="password" type="java.lang.String" column="user_password"></property>
<property name="createTime" type="java.sql.Date" column="user_create_time"></property>
</class>
</hibernate-mapping>
2、BookDTO对应的映射文件book.hbm.xml,其代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.androidxx.hibernatedemo.dto">
<class name="BookDTO" table="tb_book">
<id name="bookId" column="book_id" type="java.lang.Long">
<generator class="identity"/>
</id>
<property name="bookName" column="book_name" type="java.lang.String"/>
<property name="bookPrice" column="book_price" type="java.lang.Integer"/>
<!-- many-to-one是多对一的配置,其中name表示在BookDTO中的userDto属性,column中配置的是tb_book表的外键book_author_id -->
<!-- class中配置的是多对一中的“一”所对应的对象UserDTO,此处之所以能直接写UserDTO,是因为hibernate-mapping中的package属性已经指定了包名 -->
<many-to-one name="userDto" column="book_author_id" class="UserDTO" cascade="all"/>
</class>
</hibernate-mapping>
其中cascade熟悉表示“串联”,取值all,表示所有的操作(增删改)将执行关联操作。
四、使用Hibernate的多对一关系进行增删查改。
1、多对一关联新增
public static void main(String[] args) {
test2();
}
private static void test2() {
//加载hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//读取user.hbm.xml文件,并创建session工厂
SessionFactory sessionFactory = cfg.buildSessionFactory();
//获取session对象,相当于jdbc的connection对象。可以通过session完成CURD操作
Session session = sessionFactory.openSession();
//新增数据
Transaction transaction = session.beginTransaction();
UserDTO userDto = new UserDTO();
userDto.setUserName("javen2016");
userDto.setPassword("123456");
userDto.setCreateTime(new Date(System.currentTimeMillis()));
BookDTO bookDto = new BookDTO();
bookDto.setBookName("JavaEE从入门到放弃");
bookDto.setBookPrice(300);
bookDto.setUserDto(userDto);
session.save(bookDto);
transaction.commit();
session.close();
sessionFactory.close();
}
以上代码执行完成之后,在数据库的tb_user表和tb_book表中将同时新增一条记录。
2、多对一关联查询
public static void main(String[] args) {
test2();
}
private static void test2() {
//加载hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//读取user.hbm.xml文件,并创建session工厂
SessionFactory sessionFactory = cfg.buildSessionFactory();
//获取session对象,相当于jdbc的connection对象。可以通过session完成CURD操作
Session session = sessionFactory.openSession();
//查询数据
Query query = session.createQuery("from BookDTO");
List<BookDTO> books = query.getResultList();
for (int i = 0; i < books.size(); i++) {
BookDTO book = books.get(i);
System.out.println(book.getUserDto().getUserName() + "--" + book.getBookName());
}
session.close();
sessionFactory.close();
}
仅仅是查询BookDTO会自动将UserDTO的信息关联查询出来。
3、多对一关联修改
public static void main(String[] args) {
test3();
}
private static void test3() {
//加载hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//读取user.hbm.xml文件,并创建session工厂
SessionFactory sessionFactory = cfg.buildSessionFactory();
//获取session对象,相当于jdbc的connection对象。可以通过session完成CURD操作
Session session = sessionFactory.openSession();
//修改数据
Transaction transaction = session.beginTransaction();
UserDTO userDto = new UserDTO();
userDto.setUserId(6L);//因为是修改,所以必须指定一个已经存在的Id
userDto.setUserName("javen333");
userDto.setPassword("33333");
userDto.setCreateTime(new Date(System.currentTimeMillis()));
BookDTO bookDto = new BookDTO();
bookDto.setBookId(4L);//因为是修改,所以必须指定一个已经存在的Id
bookDto.setBookName("Android九阴真经3");
bookDto.setBookPrice(500);
bookDto.setUserDto(userDto);
session.update(bookDto);
transaction.commit();
session.close();
sessionFactory.close();
}
4、多对一关联删除
多对一的关联删除执行session.delete方法即可。多对一的删除是不会将“一”对应的表中的数据删掉的。只有在一对多关系中,将主表中的数据删除,会将从表中相关的数据一并删除。
最后
以上就是多对一的基本操作。其实多对一反过来就是一对多,但是在实际项目开发中,为什么要分多对一和一对多这2中情况呢,因为我们业务逻辑操作过程中,又是是以多的一段进行主要操作,这就也需要多对一关联;又是是以“一”这端作为主要操作,所以又需要一对多关联。
本系列案例中的代码仅仅是在main方法中进行的测试,也是为了简化代码,让Hibernate的特征不受到其他东西的干扰。
唧唧复唧唧,鸡鸡何其多。