映射文件(hbm.xml): 是配置对象与数据库表的对应关系。是站在对象的位置上进
行配置的。* hibernate-mapping元素, package:指定一个包前缀,如果在映射文档中
没有指定全限定的类名,就使用这个作为包名。auto-import:指定是否可以在查
询语言中使用非全限定名(仅限于本映射文件中的类),默认为true。
Java是面向对象语言,对象模型,其主要概念有:继承、关联、多态等;关系型
数据库中的概念有:表、主键、外键等。当使用Jdbc去操作关系型数据库时,因
为他们对应不起来,所以要做转换(转换的过程就叫做ORM, Object Relation
Mapping, 对象关系映射)。除了手工转换外,还可以使用ORM框架来解决,当前
主流ORM框架有Hibernate和TopLink等,我们学习的是Hibernate(3.2.6).
准备环境:
1,引入jar包,最基本的包为:
hibernate3.jar
antlr-2.7.6.jar
asm.jar
asm-attrs.jar
cglib-2.1.3.jar
dom4j-1.6.1.jar
commons-collections-2.1.1.jar
commons-logging-1.0.4.jar
jta.jar
所用的数据库的JDBC驱动
可以选择加入log4j-1.2.11.jar。
2,拷贝配置文件hibernate.cfg.xml到classpath的根中,并修改其中的数据
库连接信息。选择拷贝log4j.properties文件。
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///test</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 显示sql语句 -->
<property name="show_sql">true</property>
<!-- 自动更新表结构 -->
<property name="hbm2ddl.auto">update</property>
Hibernate映射文件就是用于说明Java对象与数据库表中的记录的对应关系的。不
能性质的属性(例如主键和普通属性)用不同的标签来映射,如果Java对象中的
某个属性不需要存储到数据库中,那么就不需要在映射文件中配置这个属性。
User.java
package cn.itcast.demo.entities;
import java.util.Date;
public class User {
private int id;
private String name;
private String desc;
private Date birthday;
private byte[] avatar;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public byte[] getAvatar() {
return avatar;
}
public void setAvatar(byte[] avatar) {
this.avatar = avatar;
}
@Override
public String toString() {
return new StringBuffer()//
.append("[User: id=").append(id) //
.append(",name=").append(name)//
.append("]")//
.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final User other = (User) obj;
if (id != other.id)
return false;
return true;
}
}
加入User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.demo.entities">
<class name="User" table="itcast_user" >
<id name="id" unsaved-value="undefined">
<generator class="native" />
</id>
<property name="name" type="string"/>
<property name="birthday" type="date"/>
<property name="desc" column="desc_" type="text"/>
<property name="avatar" length="512000" type="binary"/>
<!--
<property name="avatar" >
<column name="avatar" sql-type="MEDIUMBLOB"/>
</property>
-->
</class>
</hibernate-mapping>
在hibernate中加入这个映射文件。 <mapping resource="cn/itcast/demo/entities/User.hbm.xml"/>
建个用户类:
package cn.itcast.demo.test;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import cn.itcast.demo.entities.User;
public class First {
public static void main(String[] args) throws Exception {
User user = new User();
// user.setId(3);
user.setName("zhangsan");
user.setBirthday(new Date());
user.setDesc("just for test");
File file = new File("c:/default.gif");
FileInputStream fis = new FileInputStream(file);
byte[] avatar = new byte[(int) file.length()];
fis.read(avatar);
fis.close();
user.setAvatar(avatar);
Configuration cfg = new Configuration();
cfg.configure("hibernate.cfg.xml");
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
}
}
UserDao.java
package cn.itcast.demo.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import cn.itcast.demo.entities.User;
public class UserDao {
private Configuration cfg = new Configuration().configure();
private SessionFactory sessionFactory = cfg.buildSessionFactory();
public void save(User user) {
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
session.save(user);
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new RuntimeException(e);
} finally {
if (session != null) {
session.close();
}
}
}
public void delete(int id) {
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
User user = (User) session.get(User.class, id);
session.delete(user);
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new RuntimeException(e);
} finally {
if (session != null) {
session.close();
}
}
}
public void update(User user) {
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
session.update(user);
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new RuntimeException(e);
} finally {
if (session != null) {
session.close();
}
}
}
public User get(int id) {
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
User user = (User) session.get(User.class, id);
tx.commit();
return user;
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new RuntimeException(e);
} finally {
if (session != null) {
session.close();
}
}
}
@SuppressWarnings("unchecked")
public List<User> find(int first, int max) {
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
String hql = "from User";
List users = session.createQuery(hql)//
.setFirstResult(first)//
.setMaxResults(max)//
.list();
tx.commit();
return users;
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new RuntimeException(e);
} finally {
if (session != null) {
session.close();
}
}
}
}
这里我们要对上面的代码要进行测试,这样就用到jutil这样的测试工具,需要导入junit.jar才可以。之后建立个jutil测试类。
要注意的就是在所要测试的方法前,要加@Test。
UserDaoTest.java:
package cn.itcast.demo.dao;
import java.util.List;
import org.junit.Test;
import cn.itcast.demo.entities.User;
public class UserDaoTest {
private UserDao userDao = new UserDao();
@Test
public void testSave() {
User user = new User();
user.setName("lisi");
userDao.save(user);
}
@Test
public void testDelete() {
User user = new User();
user.setName("testDelete");
userDao.save(user);
userDao.delete(user.getId());
}
@Test
public void testUpdate() {
User user = new User();
user.setName("xx");
userDao.save(user);
user.setName("testUpdate");
userDao.update(user);
}
@Test
public void testGet() {
User user = new User();
user.setName("testGet");
userDao.save(user);
User u = userDao.get(user.getId());
System.out.println(u);
}
@Test
public void testFind() {
List<User> users = userDao.find(3, 3);
for (User user : users) {
System.out.println(user);
}
}
}
注意点:如果下面的测试成功的话呢,出现的就是绿色的进度条,错误的就是红色的进度条,并报有相对应的错。
Session的几个主要方法
1.save,persist,保存数据
2.delete,删除对象
3.update,更新对象,如果数据库中没有记录,会出现异常。
4.get,根据ID查,会立刻访问数据库。
5.Load,根据ID查,(返回的是代理,不会立即访问数据库)。
6.saveOrUpdate,merge,由Hibernte来确定是save或update
3,Hibernate对象实例的三种状态与Session的方法:
三种状态:自由(瞬时)、持久、游离;
自由(瞬时)状态:从未与任何Session关联过,一般指新创建的对象实例。
持久状态:目前正与Session有关联,拥有持久化标识(相当于主键值),
并且相关联的session没有关闭,事务没有提交。持久对象状态发
生改变,在事务提交时会更新到数据库。
游离状态:曾经与Session关联过,不过那个Session已经关闭了。
三种状态之间的转换(通过Session的方法):
Session的方法:save(persist), delete, get, load.
update:update是把一个已经更改过的脱管状态的对象变成持久状态。
saveOrUpdate(merge):【什么下情况添加什么情况下更新】;
使用save和saveOrUpdate方法时,如果被操作对象与另一个跟本session
关联的po对象拥有相同的持久化标识(identifier),就会抛出一个异常:
org.hibernate.NonUniqueObjectException。
通常下面的场景会使用update()或saveOrUpdate():程序在第一个
session 中加载对象,接着把session关闭,该对象被传递到表现层,对
象发生了一些改动,该对象被返回到业务逻辑层最终到持久层,程序创建
第二session调用第二个session的update()方法持久这些改动。
contains:Session是否包含某个对象(是否是持久状态);
clear:清空一级缓存;
flush:强制刷出(更新到数据库);
load与get的区别:
get方法:如果找不到符合条件的纪录,返回null。
load方法:返回的是一个代理对象。在第一次访问这些懒加载对象(代理对
象)的属性(getId方法除外)时,hibernate 会初始化这些代理。这
时如果数据库中没有与之对应的记录,就会抛异常:
org.hibernate.ObjectNotFoundException: No row with the given
identifier exists: ...。
如果PO是final的,则load被调用时会马上发出一条select语句(即不能使
用懒加载功能)。
package cn.itcast.demo.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import cn.itcast.demo.entities.User;
public class SessionTest {
@Test
public void test() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
// ----------------------------
// 1, test get() and load()
// User user = (User) session.get(User.class, 10);
// User user = (User) session.load(User.class, 1);
// System.out.println(user.getId());
// System.out.println(user.getName());
// System.out.println(user);
// 2, test save() and flush() and update() and delete
// User user = new User();
// user.setId(12);
// user.setName("xxx");
// session.save(user);
// User user = (User) session.get(User.class, 1);
// user.setName("yyy2");
// session.update(user);
// session.flush();
// session.delete(user);
// 3, test saveOrUpdate()
// User user = new User();
// user.setName("aa");
// User user = (User) session.get(User.class, 2);
// User user = new User();
// user.setId(8);
// user.setName("xxxyyy");
// session.saveOrUpdate(user);
User user = new User();
user.setId(2);
user.setName("aaa");
session.update(user);
// session.update(user);
// User user2 = new User();
// user2.setId(2);
// user2.setName("bbb");
// session.update(user2);
// 4, test evict() and clear()
// User user = (User) session.get(User.class, 2);
// boolean b = session.contains(user);
// System.out.println(b);
//
// // session.evict(user);
// session.clear();
//
// b = session.contains(user);
// System.out.println(b);
// ----------------------------
System.out.println("--- commiting...");
tx.commit();
session.close();
}
}
在学习的过程中,初学者经常会出现的一些典型的错误;
第一个:就是Hibernate的HQL查询的是对象,而sql查询的是表。
String hql = "from User";记住是User不是user;
第二个就是关于映射的问题。一定要记住,每生成一张hbm。xml表就要在hibernate.cfg.xml中映射。
还有的许多注意点,汤老师都做了详细的总结。