一. 单例工厂类
因为我们每一个测试方法都需要读取配置文件,创建工程,创建session,所以我们可以写这样子的一个工具类来做这些操作:
public class HibernateUtil {
private static Configuration cfg = null;
private static SessionFactory factory = null;
static {
if (cfg == null) {
cfg = new Configuration().configure();
}
if (factory == null) {
factory = cfg.buildSessionFactory();
}
}
public static SessionFactory getSessionFactory() {
return factory;
}
public static Session getSession() {
return factory.openSession();
}
public static void closeSession(Session session) {
if (session != null) {
session.close();
}
}
<span style="font-family:Microsoft YaHei;">}</span>
这样就大大简化了我们的代码。二. 持久化对象的三种状态
1. 瞬时对象
使用new操作符初始化的对象不是立刻就持久的,是瞬时的。
2. 持久化对象
在使用sql的insert、update、delete语句吧内存中的对象同步到数据库中,即当持久对象修改数据的时候,会自动同步到数据库中。
3. 离线状态
在session关闭之后就处于离线状态,不能同步数据到数据库中了,可以使用sql的insert、update、delete语句重新实现持久化,同步数据。
三. Session的常用方法
1. save和saveOrUpdate的区别
我们这样子修改添加的方法:
public void testAdd() {
User user = new User();
user.setUsername("张三");
user.setSex("男");
user.setAge(27);
user.setBirthday(new Date());
user.setSalary(100.5);
user.setId(2);
Session session = HibernateUtil.getSession();
// 创建及开启事务对象
Transaction trans = null;
try {
trans = session.beginTransaction();
// 添加User实体对象
session.save(user);
trans.commit();
} catch (HibernateException e) {
trans.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession(session);
}
}
给User指定了id,但是发现查看数据库,还是递增的向后排,并没有理我们的设定的id为2,相当于执行了save方法。将save改成saveOrUpdate方法,执行发现将id为2的内容修改成了我们设置的User,相当于执行了update方法;如果setId传了一个数据库不存在的值,那么它执行的又变回了save方法。
还有一点需要注意的是不论是save方法还是saveOrUpdate方法对持久对象不起作用。
/**
* save和saveOrUpdate方法对持久对象都不起作用
*/
public void testAdd2() {
Session session = HibernateUtil.getSession();
// 创建及开启事务对象
Transaction trans = null;
try {
trans = session.beginTransaction();
// 添加User实体对象
User user = (User) session.get(User.class, 2);
session.save(user);
// session.saveOrUpdate(user);
trans.commit();
} catch (HibernateException e) {
trans.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession(session);
}
}
执行发现,并没有添加新的数据出来,当修改user的数据时,是持久对象发生了同步update方法,并不是save或者saveOrUpdate起了作用。2. persist和save以及merge和update的区别
persist和save都可以把对象存进数据库,没有什么区别。
接下来我们看这个方法:
public void testUpdate() {
User user = new User();
user.setUsername("陈小春");
user.setSex("男");
user.setAge(40);
user.setBirthday(new Date());
user.setSalary(110.5);
user.setId(3);
Session session = HibernateUtil.getSession();
// 创建及开启事务对象
Transaction trans = null;
try {
trans = session.beginTransaction();
User u = (User) session.get(User.class, 3);
session.update(user);
trans.commit();
} catch (HibernateException e) {
trans.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession(session);
}
}
执行后会发现报错了,说有两个相同id的实体,这里修改成merge而不是update的时就会正常执行。实际上执行merge方法时,会先将merge参数中user的全部属性赋值给u对象,然后更新u对象。3. lock(已淘汰)和update方法的区别
lock是原来为了将对象重新持久化而使用的一个方法,现在已经废弃了,使用update代替了。
4. save、update、get、delete方法的执行顺序和flush方法
在一个session的执行过程中,不管save、update、get和delete写在程序的哪里,他们的执行顺序都是先get,然后save,然后update最后delete,如果想要先执行某个方法,那么需要在这个方法之后调用flush方法即可:
public void testOrder() {
User user = new User();
user.setUsername("第一个");
user.setSex("男");
user.setAge(27);
user.setBirthday(new Date());
user.setSalary(100.5);
user.setId(2);
Session session = HibernateUtil.getSession();
// 创建及开启事务对象
Transaction trans = null;
try {
trans = session.beginTransaction();
User u = (User) session.get(User.class, 10);
u.setUsername("更新的第10条");
session.delete(session.get(User.class, 7));
session.delete(session.get(User.class, 8));
session.flush();
// 添加User实体对象
session.save(user);
user = new User();
user.setUsername("新的一个");
user.setAge(17);
user.setBirthday(new Date());
user.setSalary(294.4);
user.setSex("女");
session.save(user);
trans.commit();
} catch (HibernateException e) {
trans.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession(session);
}
}
5. clear及evict方法
public void testclear() {
Session session = HibernateUtil.getSession();
// 创建及开启事务对象
Transaction trans = null;
try {
trans = session.beginTransaction();
Query query = session
.createQuery("from com.thr.hibernate.entity.User");
List<User> users = query.list();
// session.clear();
for (User user : users) {
user.setUsername(user.getUsername() + "new");
}
trans.commit();
} catch (HibernateException e) {
trans.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession(session);
}
}
当执行了query.list方法后,查询出来的集合已经放在了缓存中,可以持久化更新,但是如果执行了session.clear()方法后,那么缓存就都清空了,后面的users并不持久化,无法更新了。修改代码:
int i = 0;
for (User user : users) {
i++;
if (i == 3) {
session.evict(user);
}
user.setUsername(user.getUsername() + "new");
}
意思是当执行到第3个元素的时候,将其从缓存中剔除掉,那么第3个元素就不会执行更新语句了。6. get和load方法的区别
public void test() {
Session session = HibernateUtil.getSession();
// 创建及开启事务对象
Transaction trans = null;
try {
trans = session.beginTransaction();
//User user = (User) session.get(User.class, 10);
User user = (User) session.load(User.class, 10);
System.out.println(user.getUsername());
trans.commit();
} catch (HibernateException e) {
trans.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession(session);
}
}
使用get方法的时候在执行get方法后,立刻就进行了查询操作;但使用load方法会延时加载,在需要使用到user的时候才会执行查询的操作。是否开启懒加载还可以在hibernate的配置文件中通过配置lazy="false"来设置:<span style="white-space:pre"> </span><class name="com.thr.hibernate.entity.User" table="T_USER" lazy="true">
当查询不到结果的时候get方法会返回null,而load方法会报异常。7. list和iterator方法
public void testIterator() {
Session session = HibernateUtil.getSession();
// 创建及开启事务对象
Transaction trans = null;
try {
trans = session.beginTransaction();
Query query = session
.createQuery("from com.thr.hibernate.entity.User");
// List<User> users = query.list();
// for (User user : users) {
// System.out.println(user);
// }
Iterator<User> it = query.iterate();
while (it.hasNext()) {
System.out.println(it.next());
}
it = query.iterate();
while (it.hasNext()) {
System.out.println(it.next());
}
trans.commit();
} catch (HibernateException e) {
trans.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession(session);
}
}
使用注释中的list方法是执行了一条查询,直接查出了所有的数据,如果第二次执行list还是会查询所有的数据;而使用iterator第一次查询是查出了所有的id,然后使用id去查询每一条数据,如果有第二次的话,还是去查询所有的id,如果发现和第一次id有一样的,会直接使用第一次的数据,没有多余的操作。