断断续续的看hibernate有好几天了。每当学了一点点的知识,我都要思考hibernate的价值、或者站在另一个角度去思考。还好了,让我更加深刻的理解了hibernate的作用。
其实hibernate就相当于java的专有数据库。根据java EE的特性——多用户、大量访问,那么自然就不能手工的直接去操作数据库了,因为当我们手动的去操作的时候很多时候都会造成一些冗余操作,你如果给数据库发送两个请求,那么数据库也就会不折不扣的执行两个操作,然而令人悲哀的是:数据库是存储在硬盘上的,需要通过io进行操作,那么也就会使得网站的数据库操作部分变成一个瓶颈。那么就这样hibernate诞生了,它提供了一个虚拟的java数据库,让我们“做好了真正想要做的‘所有’决定”,然后一次性的发送给数据库,一次性完成操作,无意这样就会减少很多的io操作,让我们的系统变得更加的速度。
以上是我理解的hibernate的价值。暂不思考其在项目分模块、分层方面的价值。
其实我觉得学习hibernate的时候,要先复习一下数据库,从数据库的角度去学习hibernate,数据库中所有的操作在hibernate中都会体现,这样才能使得我们变成知识的主动接受者。
回归正题,这次要总结的是hibernate中的一对多双向关系。
所谓的一对多就是,甲方可以包含多个乙方的引用,而乙方只可以包含有一个甲方的引用。所以呢,我们就需要先建立两个模型:student类和course类(此处并不合适,因为一个学生可以选择多门课,而且一门课也可由多个学生选择,此处仅仅为了表达如何的实现hibernate的一对多)。
代码:
注:代码很简单、基本就不加注释了。。。
Student.java
package com.dong.model;
import java.util.List;
import java.util.Set;
public class Student
{
private Long id;
private String name;
private int age;
private Set<Course> courses;
public Student(){}
public Student(Long id, String name, int age, Set<Course> courses)
{
this.id = id;
this.name = name;
this.age = age;
this.courses = courses;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public Set<Course> getCourses()
{
return courses;
}
public void setCourses(Set<Course> courses)
{
this.courses = courses;
}
}
Course.java
package com.dong.model;
public class Course
{
private Long id;
private String name;
private Student student;
public Course(){}
public Course(Long id, String name, Student student)
{
this.id = id;
this.name = name;
this.student = student;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Student getStudent()
{
return student;
}
public void setStudent(Student student)
{
this.student = student;
}
}
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 连接的URL --> <property name="connection.url"> jdbc:mysql://localhost:3306/hibernate </property> <!-- 登录数据库的用户名 --> <property name="connection.username">root</property> <!-- 登录数据库的密码 --> <property name="connection.password">wlzjdm</property> <!-- 连接数据库的驱动 --> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <!-- 采用的会话方言,也就是告诉hibernate此次连接的是什么数据库,采用哪种数据库语言 --> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <!-- 是否打印hibernate自动生成的SQL语句,为了方便测试,此处设置为true,当我们部署的时候应该设置为false --> <property name="show_sql">true</property> <!-- 模型与数据库表的关联配置 --> <mapping resource="Student.hbm.xml"/> <mapping resource="Course.hbm.xml"/> </session-factory> </hibernate-configuration>
Student.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.dong.model.Student" table="student"> <id name="id" type="long"> <generator class="increment"/> </id> <property name="name" type="string"/> <property name="age" type="integer"/> <set name="courses" cascade="all" inverse="true"> <key column="stu_id"/> <one-to-many class="com.dong.model.Course"/> </set> </class> </hibernate-mapping>
Course.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.dong.model.Course" table="course"> <id name="id" type="long"> <generator class="increment" /> </id> <property name="name" type="string"/> <many-to-one name="student" column="stu_id"/> </class> </hibernate-mapping>
测试类,我采用了多线程的方式进行了测试,更加深一步的证明了hibernate中存在一个虚拟的数据库系统。
package com.dong.test;
import java.util.HashSet;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.dong.model.Course;
import com.dong.model.Student;
public class TestOneToMany
{
private static SessionFactory factory;
static
{
try
{
factory = new Configuration().configure().buildSessionFactory();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
TestOneToMany t = new TestOneToMany();
t.mulThreadTest(10000);
t.mulThreadTest(0);
t.mulThreadTest(0);
}
private void mulThreadTest(final long time)
{
Thread t1 = new Thread()
{
@Override
public void run()
{
Session session = null;
Transaction tx = null;
try
{
session = factory.openSession();
tx = session.beginTransaction();
Student s1 = new Student();
s1.setName("dong");
s1.setAge(22);
s1.setCourses(new HashSet<Course>());
Course cs1 = new Course();
cs1.setName("math");
cs1.setStudent(s1);
Course cs2 = new Course();
cs2.setName("english");
cs2.setStudent(s1);
s1.getCourses().add(cs1);
s1.getCourses().add(cs2);
session.save(s1);
System.out.println(this.getId() + ":" + s1.getId());
Thread.sleep(time);
System.out.println(this.getId() + ":" + s1.getId());
tx.commit();
System.out.println(this.getId() + ":" + s1.getId());
}
catch (Exception e)
{
if (tx != null)
{
tx.rollback();
}
}
finally
{
if (session != null)
{
session.close();
}
}
}
};
t1.start();
}
}