ORM(Object/Relationship Mapping):对象关系映射
利用面向对象思想编写的数据库应用程序最终都是把对象信息保存在关系型数据库中,于是要编写很多和底层数据库相关的SQL语句。这与面向对象的思想格格不入。所以需要一种ORM框架技术,使其真正的面向对象。Hibernate就是这样一种框架。
SQL语句的不好之处
1. 在不同的数据库使用的SQL语法不同,比如:PL/SQL与T/SQL
2. 同样的功能在不同的数据库中有不同的实现方式。比如分页SQL技术
3. 程序过分依赖SQL对程序的移植及拓展,维护等带来很大的麻烦。
Hibernate是java领域的一款开源的ORM框架技术。
Hibernate对JDBC进行了非常轻量级的对象封装。
Eclipse,MySQL
Hibernate Tools for Eclipse Plugins
Hibernate Tools是由JBoss推出的一个Eclipse综合开发工具插件,该插件可以简化ORM框架Hibernate,以及JBoss Seam,EJB3等的开发工作。
需要导入的jar包
导入Hibernate必须的jar包
hibernate-release-4.2.4.Final\lib\required
导入Mysql的jdbc驱动
导入Junit4的jar包
Hibernate配置文档hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="connection.username">rootproperty>
<property name="connection.password">123property>
<property name="connection.driver_class">com.mysql.jdbc.Driverproperty>
<property name="connection.url">jdbc:mysql:///hibernate?useUnicode=true&characterEncoding=UTF-8property>
<property name="dialect">org.hibernate.dialect.MySQLDialectproperty>
<property name="show_sql">trueproperty>
<property name="format_sql">trueproperty>
<property name="hbm2ddl.auto">createproperty>
<mapping resource="Students.hbm.xml"/>
session-factory>
hibernate-configuration>
持久化类Students.java
import java.util.Date;
//学生类(持久化类,满足javabean的设计原则)
public class Students {
// 1.公有的类
// 2.提供公有的不带参数的默认构造方法
// 3.属性私有
// 4.属性必须封装
private int sid;
private String sname;
private String gender;
private Date birthday;
private String address;
public Students() {
}
public Students(int sid, String sname, String gender, Date birthday,
String address) {
// super();
this.sid = sid;
this.sname = sname;
this.gender = gender;
this.birthday = birthday;
this.address = address;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
// 方便测试,重写tostring方法
@Override
public String toString() {
return "Students [sid=" + sid + ", sname=" + sname + ", gender="
+ gender + ", birthday=" + birthday + ", address=" + address
+ "]";
}
}
对象关系映射文件Students.hbm.xml
<hibernate-mapping>
<class name="Students" table="STUDENTS">
<id name="sid" type="int">
<column name="SID" />
<generator class="assigned" />
id>
<property name="sname" type="java.lang.String">
<column name="SNAME" />
property>
<property name="gender" type="java.lang.String">
<column name="GENDER" />
property>
<property name="birthday" type="java.sql.Date">
<column name="BIRTHDAY" />
property>
<property name="address" type="java.lang.String">
<column name="ADDRESS" />
property>
class>
hibernate-mapping>
测试类StudentsTest.java
//测试类
public class StudentsTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void Init() {
// 创建事物对象
Configuration config = new Configuration().configure();
// 创建服务器注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
//创建会话工厂对象
sessionFactory = config.buildSessionFactory(serviceRegistry);
//会话对象
session = sessionFactory.openSession();
//开启事务
transaction = session.beginTransaction();
}
@After
public void destory() {
transaction.commit();//提交事务
session.close();//关闭会话
sessionFactory.close();//关闭会话工厂
}
@Test
public void testSaveStudents() {
//生成学生对象
Students s = new Students(1, "张三丰", "男", new Date(), "武当山");
session.save(s);//把对象保存进数据库
}
}
<propertyname="hibernate.current_session_context_class">threadproperty>
如果是全局事务(jta事务)
<propertyname="hibernate.current_session_context_class">jtaproperty>
public class SessionTest {
// 以下两个测试方法用于测试两种获得session对象的区别
@Test
public void testOpenSession() {
// 获得配置对象
Configuration config = new Configuration().configure();
// 获得服务器注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
// 获得sessionFactory对象
SessionFactory sessionFactory = config
.buildSessionFactory(serviceRegistry);
// 获得session对象
Session session1 = sessionFactory.openSession();
Session session2 = sessionFactory.openSession();
//证明openSession每次创建新的session对象
System.out.println(session1 == session2);// false
// if (session != null) {
// System.out.println("session创建成功!");
// } else {
// System.out.println("session创建失败!");
// }
}
@Test
public void testGetCurrentSession() {
// 获得配置对象
Configuration config = new Configuration().configure();
// 获得服务器注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
// 获得sessionFactory对象
SessionFactory sessionFactory = config
.buildSessionFactory(serviceRegistry);
// 获得session对象
// 必须在hibernate.cfg.xml中配置
// name="hibernate.current_session_context_class">thread
//否则session创建失败
Session session1 = sessionFactory.getCurrentSession();
Session session2 = sessionFactory.getCurrentSession();
//证明getCurrentSession()每次使用现有的session对象
System.out.println(session1 == session2);// true
// if (session != null) {
// System.out.println("session创建成功!");
// } else {
// System.out.println("session创建失败!");
// }
}
// 以下两个测试方法用于测试两种获得session对象的区别之
//openSession在提交提交事务或者回滚后需要手动关闭会话,否则容易导致连接池溢出
//而getCurrentSession提交后会自动关闭
@Test
public void testSaveStudentsWithOpenSession() {
// 获得配置对象
Configuration config = new Configuration().configure();
// 获得服务器注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
// 获得sessionFactory对象
SessionFactory sessionFactory = config
.buildSessionFactory(serviceRegistry);
// 创建session对象
Session session1 = sessionFactory.openSession();
// 开启事务
Transaction transaction = session1.beginTransaction();
// 生成一个学生对象
Students s = new Students(1, "张三", "男", new Date(), "北京");
//两次的打印的hashcode不同,说明两次用的不是同一个session。
session1.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
System.out.println("connection hashCode:"
+ connection.hashCode());
}
});
session1.save(s);
// session1.close();
transaction.commit();// 提交事务
Session session2 = sessionFactory.openSession();
transaction = session2.beginTransaction();
s = new Students(2, "李四", "男", new Date(), "上海");
session2.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
System.out.println("connection hashCode:"
+ connection.hashCode());
}
});
session2.save(s);
transaction.commit();
}
@Test
public void testSaveStudentsWithGetCurrentSession() {
// 获得配置对象
Configuration config = new Configuration().configure();
// 获得服务器注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
// 获得sessionFactory对象
SessionFactory sessionFactory = config
.buildSessionFactory(serviceRegistry);
// 创建session对象
Session session1 = sessionFactory.getCurrentSession();
// 开启事务
Transaction transaction = session1.beginTransaction();
// 生成一个学生对象
Students s = new Students(1, "张三", "男", new Date(), "北京");
session1.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
System.out.println("connection hashCode:"
+ connection.hashCode());
}
});
session1.save(s);
// session1.close();
transaction.commit();// 提交事务
Session session2 = sessionFactory.getCurrentSession();
transaction = session2.beginTransaction();
s = new Students(2, "李四", "男", new Date(), "上海");
session2.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
System.out.println("connection hashCode:"
+ connection.hashCode());
}
});
session2.save(s);
transaction.commit();
}
}
//学生类(持久化类,满足javabean的设计原则)
public class Students {
// 1.公有的类
// 2.提供公有的不带参数的默认构造方法
// 3.属性私有
// 4.属性必须封装
private int sid;
private String sname;
private String gender;
private Date birthday;
// private String address;
//对象类型
private Blob picture;
//组件属性
private Address address;
public Students() {
}
public Students(int sid, String sname, String gender, Date birthday,
String address) {
// super();
this.sid = sid;
this.sname = sname;
this.gender = gender;
this.birthday = birthday;
//this.address = address;
}
//、、、、、、
students.hbm.xml
<hibernate-mapping>
<class name="Students" table="STUDENTS">
<id name="sid" type="int">
<column name="SID" />
<generator class="assigned" />
id>
<property name="sname" type="java.lang.String">
<column name="SNAME" />
property>
<property name="gender" type="java.lang.String">
<column name="GENDER" />
property>
<property name="birthday" type="java.util.Date">
<column name="BIRTHDAY" />
property>
<property name="picture" type="java.sql.Blob">
<column name="PICTURE" />
property>
<component name="address" class="Address">
<property name="postcode" column="POSTCODE"/>
<property name="phone" column="PHONE"/>
<property name="address" column="ADDRESS"/>
component>
class>
hibernate-mapping>
StudentsTest.java
//测试类
public class StudentsTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void Init() {
// 创建事物对象
Configuration config = new Configuration().configure();
// 创建服务器注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
// 创建会话工厂对象
sessionFactory = config.buildSessionFactory(serviceRegistry);
// 会话对象
session = sessionFactory.openSession();
// 开启事务
transaction = session.beginTransaction();
}
@After
public void destory() {
transaction.commit();// 提交事务
session.close();// 关闭会话
sessionFactory.close();// 关闭会话工厂
}
// 测试主键
//测试组合属性
//1.创建组合属性类(Address) 2.修改实体类(Students) 3.修改映射文件
@Test
public void testSaveStudents() {
// 生成学生对象
// Students s = new Students(1, "张三丰", "男", new Date(), "武当山");
Students s = new Students();
s.setSid(100);// 当 时,这行代码不起作用
s.setSname("张三丰");
s.setGender("男");
s.setBirthday(new Date());
//s.setAddress("武当山");
Address address = new Address("710068", "029888888", "武汉市");
s.setAddress(address);//数据库address列变为三列了
session.save(s);// 把对象保存进数据库
}
//测试Blob(向数据库存储照片)
@Test
public void testWriteBlob() throws Exception{
Students s = new Students(2, "张三丰", "男", new Date(), "武当山");
//先获取照片文件
File f = new File("d:"+File.separator+"boy.jpg");
//获得照片文件的输入流
InputStream input = new FileInputStream(f);
//创建一个Blob对象
Blob image = Hibernate.getLobCreator(session).createBlob(input, input.available());
//设置照片属性
s.setPicture(image);
//保存学生
session.save(s);
}
//测试向数据库读取Blob数据(照片)
@Test
public void testReadBlob() throws Exception{
Students s = (Students) session.get(Students.class,2);
//获取Blob对象
Blob image = s.getPicture();
//获得照片的输入流
InputStream input = image.getBinaryStream();
//创建输出流
File f = new File("d:"+File.separator+"dest.jpg");
//获得输出流
OutputStream output = new FileOutputStream(f);
//创建缓冲区
byte[] buff = new byte[input.available()];
input.read(buff);
output.write(buff);
input.close();
output.close();
}
}
//测试类
public class StudentsTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void Init() {
// 创建事物对象
Configuration config = new Configuration().configure();
// 创建服务器注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
// 创建会话工厂对象
sessionFactory = config.buildSessionFactory(serviceRegistry);
// 会话对象
session = sessionFactory.openSession();
// 开启事务
transaction = session.beginTransaction();
}
@After
public void destory() {
transaction.commit();// 提交事务
session.close();// 关闭会话
sessionFactory.close();// 关闭会话工厂
}
// 测试主键
// 测试组合属性
// 1.创建组合属性类(Address) 2.修改实体类(Students) 3.修改映射文件
//也测试了session.save()方法
@Test
public void testSaveStudents() {
// 生成学生对象
// Students s = new Students(1, "张三丰", "男", new Date(), "武当山");
Students s = new Students();
s.setSid(100);// 当 时,这行代码不起作用
s.setSname("张三丰");
s.setGender("男");
s.setBirthday(new Date());
// s.setAddress("武当山");
Address address = new Address("710068", "029888888", "武汉市");
s.setAddress(address);
session.save(s);// 把对象保存进数据库
}
// 测试get查询方法
@Test
public void testGetStudents() {
// 不管是否使用到s对象,查询语句会马上发出
Students s = (Students) session.get(Students.class, 100);
// 成功打印出s对象
// System.out.println(s);
// 反射技术,打印出类名,测试get方法返回的是持久化类的对象,而post方法返回的是代理对象
System.out.println(s.getClass().getName());//Students
}
// 测试load查询方法
@Test
public void testLoadStudents() {
// 如果没有用s对象,那么后台不会有任何的sql语句输出
Students s = (Students) session.load(Students.class, 100);
//这里打印输出s对象,使用到了s对象,发出了sql语句,与get方法效果一样
//System.out.println(s);
// 反射技术,打印出类名,测试get方法返回的是持久化类的对象,而post方法返回的是代理对象
System.out.println(s.getClass().getName());//Students_$$_javassist_0
}
// 测试update查询方法
@Test
public void testUpdateStudents() {
Students s = (Students) session.load(Students.class, 100);
s.setGender("女");
session.update(s);
}
// 测试delete删除方法
@Test
public void testDeleteStudents() {
Students s = (Students) session.load(Students.class, 100);
session.delete(s);
}
}