曾经学习java的时候,一開始就学习了hibernate,那时候总认为ssh很高大上,所以就急忙看了下相关视频。只是由于实际须要不高,所以后来一直没有使用上hibernate组件。如今一年过去了,也疯狂学习了java一段时间了,做过几个不大的项目,可是总算对java有些了解。如今參加了工作,公司使用的就是ssh,所以这两天又又一次開始捣鼓hibernate。这次学习直接使用editplus,直接开发。看了官网的demo,发现英语也没有想象中那么困难。哈哈,把自己的学习记录下来吧。这里主要记录三个方面:
1.怎样搭建hibernate
2.几种经常使用映射关系(one - to -one,one - to - many, many - to - one, many - to - many)
搭建hibernate(直接使用文本编辑器)
第一步:这个过程也不复杂,主要是下载到hibernate相关jar包,然后将必要的jar引入到classpath中,详细什么是classpath,大家能够百度下。假设不导入到classpath中,会出现不能找到类的异常。为什么会出现这样的情况呢?大家能够百度下,java 的类载入过程。
第二步:编写hibernate.cfg.xml文件。这个大家不用手写,直接去hibernate文章中copy一个就可以。以下给出我的代码
<?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.url">jdbc:mysql://localhost:3306/hibernate_demo</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.show_sql">true</property> <!--if the value='create, means create table, every time open hibernate, if will drop the old scheme'--> <property name="hbm2ddl.auto">update</property> <mapping resource="User.xml"/> <mapping resource="Address.xml"/> </session-factory> </hibernate-configuration>第三步:開始制作一个工具类,用来初始化hibernate组件。因为难度不高,直接给出代码,这些在文章中都已经有了,大家能够自己下载document看看。以下是代码:
import java.io.*; import org.hibernate.*; import org.hibernate.cfg.*; /** * that is a hibernate config util * */ public class HibernateConfigurationUtil{ private static HibernateConfigurationUtil singleton = new HibernateConfigurationUtil("hibernate.cfg.xml"); private static SessionFactory factory; /** * singleton pattern * */ private HibernateConfigurationUtil(String configXml){ init(configXml); } public void init(String configXml){ Configuration cfg = new Configuration().configure(new File("hibernate.cfg.xml")); factory = cfg.buildSessionFactory(); // build the session factory } public static SessionFactory getSessionFactory(){ if(factory == null) return null; return factory; } /** * open a new Session * * */ public static Session openSession(){ Session session = factory.openSession(); return session; } }
注意下,这个类使用单例设计模式,由于hibernate组建在启动Configuration时,是很耗时的,并且这个对象在启动之后不能改变,所以每一个project中,启动一次就可以。
第三步:编写BaseHibernateDao,这个类注意是封装了save, delete, update, load这四个方法。
import java.io.*; import org.hibernate.*; import org.hibernate.cfg.*; /** * that is the base hibernate dao, * it define a series of method to access database * if you want to 'delete, update a object, the object must exists in hibernate memery' * * @author luohong * @date 2014-08-07 * */ public class BaseHibernateDao{ public BaseHibernateDao(){ } /** * try to save a object * */ public void save(Object object){ Session session = HibernateConfigurationUtil.openSession(); // open transaction Transaction transaction = session.beginTransaction(); session.save(object); // commint transaction transaction.commit(); } /** * try to update a object * */ public void update(Object object){ Session session = HibernateConfigurationUtil.openSession(); // open transaction Transaction transaction = session.beginTransaction(); session.update(object); // commint transaction transaction.commit(); } /** * try to delete a object * */ public void delete(Object object){ Session session = HibernateConfigurationUtil.openSession(); // open transaction Transaction transaction = session.beginTransaction(); session.delete(object); // commint transaction transaction.commit(); } /** * try to load a object from database by className and id * */ public Object load(Class<?> className, Serializable id){ Session session = HibernateConfigurationUtil.openSession(); // there is no need for transaction return session.load(className, id); } }
注意:在save, update, delete方法中,仅仅用了Transaction,要开启事务,否则数据库找不到相关记录。
第四步:到了这里之后,就很easy了,仅仅须要针对详细的类,扩展BaseHibernateDao就可以。以下给出一个一对多的样例。模拟情景:用户(User)拥有多个住址(Address)首先给出两个类:
import java.util.*; public class User{ private int id; private String password; private String name; private Set<Address> addressSet; public void setAddressSet(Set<Address> addressSet){ this.addressSet = addressSet; } public Set<Address> getAddressSet(){ return addressSet; } public void setName(String name){ this.name = name; } public String getName(){ return name; } public void setId(int id){ this.id = id; } public int getId(){ return id; } public void setPassword(String password){ this.password = password; } public String getPassword(){ return password; } public String toString(){ return "id = " + id + ", name = " + name + ", password = " + password + ", addressSet = " + addressSet; } }
/** * that is the user address * a user have many address, but a adress belong to a user * It is the classical 1 * n relationship * @author luohong * @date 2014-08-07 * */ public class Address { //=====================properties============================= private int id; //private User belongTo; private String code; private String city; private String street; private String homeNumber; //===================setter and getter======================== public void setId(int id){ this.id = id; } public int getId(){ return id; } /* public void setBelongTo(User user){ this.belongTo = belongTo; } public User getBelongTo(){ return belongTo; } */ public void setCode(String code){ this.code = code; } public String getCode(){ return code; } public void setCity(String city){ this.city = city; } public String getCity(){ return city; } public void setHomeNumber(String homeNumber){ this.homeNumber = homeNumber; } public String getHomeNumber(){ return homeNumber; } public String getStreet(){ return street; } public void setStreet(String street){ this.street = street; } //========================toString================================ public String toString(){ return "id = " + id + ", city = " + city + ", street = " + street + ", homeNumber = " + homeNumber + ", code = " + code;// + ", belongTo = " + belongTo; } }
给出相关的User.xml, Address.xml;这个样例使用的是单向一对多。
<?xml version="1.0"?> <!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="User" table="user"> <id name="id"> <generator class="increment"/> </id> <property name="password"/> <property name="name"/> <!--one to many--> <set name="addressSet" cascade="all"> <!--define the foreight column name--> <key column="user_id"/> <!--define the foreight table name--> <one-to-many class="Address"/> </set> </class> </hibernate-mapping>
<?xml version="1.0"?> <!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="Address" table="address"> <id name="id"> <generator class="increment"/> </id> <property name="code"/> <property name="city"/> <property name="street"/> <property name="homeNumber"/> </class> </hibernate-mapping>
然后编写一个UserDao,继承BaseHibernateDao,也非常easy,哈哈,一看就懂,这就是hibernate的厉害之处。
import java.util.*; import org.hibernate.*; /** * user dao extends BaseHibernateDao * you can add new functions to the custom dao * * * @author luohong * @date 2014-08-07 * */ public class UserDao extends BaseHibernateDao{ /** * delete a user by userId * * */ public void deleteById(String id){ if (id == null) return; // do nothing String hql = "delete User where id=?"; // 1 open session Session session = HibernateConfigurationUtil.openSession(); // 2 create a query Query query = session.createQuery(hql); // 3 set the parameter to query query.setString(1, id); // 4 execute query query.executeUpdate(); } /** * find all user from database * */ public List<User> findAllUsers(){ String hql = "from User"; Session session = HibernateConfigurationUtil.openSession(); Query query = session.createQuery(hql); List userList = query.list(); return (List<User>)userList; } }
剩下的就是測试啦,come on...
import java.io.*; import java.util.*; /** * hibernate orm 框架demo * @author luohong * @date 2014-08-06 * * */ public class HibernateDemo{ public static void main(String[] args) throws Exception{ UserDao userDao = new UserDao(); User user = new User(); user.setName("luohong"); user.setPassword("luohong"); Set<Address> addressSet = new HashSet<Address>(); for(int i=0; i<3; i++){ Address address = new Address(); address.setCode("111"); address.setCity("hongkang"); address.setStreet("universal street"); address.setHomeNumber("a-2846"); //address.setBelongTo(user); addressSet.add(address); } user.setAddressSet(addressSet); userDao.save(user); } }
以下是程序的执行结果:
Hibernate: select max(id) from user Hibernate: select max(id) from address Hibernate: insert into user (password, name, id) values (?, ?, ?) Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?) Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?) Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?) <span style="color:#ff0000;">Hibernate: update address set user_id=? where id=? Hibernate: update address set user_id=? where id=? Hibernate: update address set user_id=? where id=?</span>
从执行结果我们能够看到,在这样的一对多关系中,这样的配置方式须要执行的sql是比較多的,由于hibernate是先分别插入两个表的数据,然后在更新多表一方的id值,就假设上面红色语句部分。这事实上是没有必要的,那么我们应该怎么办呢?没错,在配置一对多一的一方时,指定好 inverse="true":然后在代码里面主动设置address与user的关联,也就是address.setBelongTo(user);
<set name="addressSet" inverse="true" cascade="all"> <key column="user_id" not-null="true"/> <one-to-many class="Address"/> </set>这就代表:address讲主动获取user对象的id值,在插入前就已经获得了user的id值了,仅仅须要插入数据就可以。而没有设置inverse="true"时,则直接插入new出来的address对象,然后再更新值。
以下是增加了inverse="true"的hibernate运行语句:
Hibernate: select max(id) from user Hibernate: select max(id) from address Hibernate: insert into user (password, name, id) values (?, ?, ?) Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?) Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?) Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?)
上面的样例是基于单向的一对多,以下给出双向配置,事实上也非常easy,仅仅须要在多的一方增加:
<many-to-one name="belongTo" class="User" column="user_id" cascade="save-update" insert="false" update="false"> </many-to-one>在这里面,我们能够看到,无非就是指定关联的column,以及关联的表,而且配置级联关系。
作为一对多,另一种典型的一对多关系,那就是自关联啦。
样例:
<?xml version="1.0"?> <!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="Category" table="category"> <id name="id"> <generator class="increment"/> </id> <property name="name"/> <set name="categories" cascade="all"> <key column="parent_id"></key> <one-to-many class="Category"></one-to-many> </set> <many-to-one name="parent" class="Category" cascade="save-update" column="parent_id"> </many-to-one> </class> </hibernate-mapping>
以下使用hibernate来配置多对多...
实体类:
package net.itaem.hibernate.entity; import java.util.HashSet; import java.util.Set; /** * 建立多对多 * */ public class Student { private Integer id; private String name; private String number; private Set<Teacher> teachers = new HashSet<Teacher>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", number=" + number + "]"; } }
package net.itaem.hibernate.entity; import java.util.HashSet; import java.util.Set; public class Teacher { private Integer id; private String name; private String number; private Set<Student> students = new HashSet<Student>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } @Override public String toString() { return "Teacher [id=" + id + ", name=" + name + ", number=" + number + "]"; } }
以下是xml的配置:
<?xml version="1.0"?> <!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="net.itaem.hibernate.entity.Student" table="student"> <id name="id"> <generator class="increment"/> </id> <property name="name"></property> <property name="number"></property> <!-- 配置多对多 --> <set name="teachers" cascade="all" table="student_teacher"> <!-- 指定外键关联 --> <key column="student_id"/> <!-- 指定关联类属性 --> <many-to-many class="net.itaem.hibernate.entity.Teacher" column="teacher_id"/> </set> </class> </hibernate-mapping>
<?xml version="1.0"?> <!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="net.itaem.hibernate.entity.Teacher" table="teacher"> <id name="id"> <generator class="increment"/> </id> <property name="name"></property> <property name="number"></property> <!-- 配置多对多 --> <set name="students" inverse="true" cascade="all" table="student_teacher"> <!-- 指定外键关联 --> <key column="teacher_id"/> <!-- 指定关联类属性 --> <many-to-many class="net.itaem.hibernate.entity.Student" column="student_id"/> </set> </class> </hibernate-mapping>
然后是測试类:
package net.itaem.hibernate.dao; import java.util.HashSet; import java.util.Set; import net.itaem.hibernate.entity.Student; import net.itaem.hibernate.entity.Teacher; public class StudentDao extends BaseHibernateDao{ public static void main(String[] args) { Student student = new Student(); student.setName("student"); student.setNumber("201111701222"); Set<Teacher> teachers = new HashSet<Teacher>(); for(int i=0; i<10; i++){ Teacher t = new Teacher(); t.setName("teacher" + i); t.setNumber("20111170122" + i); teachers.add(t); } student.setTeachers(teachers); new StudentDao().save(student); System.out.println(((Student)new StudentDao().load(Student.class, new Integer(1))).getTeachers()); } }
输出结果:
Hibernate: select max(id) from student Hibernate: select max(id) from teacher Hibernate: insert into student (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into teacher (name, number, id) values (?, ?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?) Hibernate: select student0_.id as id1_2_0_, student0_.name as name2_2_0_, student0_.number as number3_2_0_ from student student0_ where student0_.id=? Hibernate: select teachers0_.student_id as student_1_2_0_, teachers0_.teacher_id as teacher_2_3_0_, teacher1_.id as id1_4_1_, teacher1_.name as name2_4_1_, teacher1_.number as number3_4_1_ from student_teacher teachers0_ inner join teacher teacher1_ on teachers0_.teacher_id=teacher1_.id where teachers0_.student_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=? Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?这样子,双向的多对多也就配置完毕了。