首先Gd要说一句,在真正的实践项目中是不建议构建单态的Session的,最好是先构建一个单态的SessionFactory,再在所用的方法中获取Session,因为Session是非线程安全的,如果构建单态的Session容易造成数据混乱,而且Session对象是轻量级对象,和SessionFactory相比不会占用太多资源。
对于像我这样的初学者来说,Hibernate中每当创建一个方法完成数据库的增删改查操作时都需要新建一个Session对象,这样会使代码显得稍有繁杂,像我们平时学习和做练习的时候还好一些,如果到了大型的项目实践中,未免显得非常麻烦。
老师上课时谈到,构建单态的Session有两种方法,一种是使用静态代码块,一种是使用私有化构造方法,课本上提到了静态代码块的实例,所以我决定两种方式都尝试一下。
通过查阅书籍和查看网上的资料发现使用私有化构造方法构建单态的Session的主要思路就是像它的描述一样——私有化构造方法,类之中的所有属性只有在调用构造方法实例化对象之后才会分配空间,如果将构造方法私有化,在类的外部便无法访问,所以我们需要定义一个公有类型的方法使外部能够访问到被私有化的构造方法。我们都知道构造方法是在创建对象时自动调用的,所以要访问构造方法,少不了要定义一个对象,使用公有类型的方法返回所创建的对象,便能够自动调用此类中的构造方法了,再在类中实例化一个Session对象,便能够实现一处实例,多处调用了。
使用静态代码块的道理和使用私有化构造方法类似,都是一处实例化,多处调用的思想。
下面是我的代码、测试过程和结果:
私有化构造方法构建单态Session:
import org.User.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
class Singleton {
private static Singleton intance = new Singleton();
private Singleton(){}
public static Singleton getInstance()
{
return intance;
}
public Session Cs()
{
return new Configuration().configure().buildSessionFactory().openSession();
}
}
public class DemoSingleton{
@Test
public void testIncrease(){
Singleton s = Singleton.getInstance();
Session session = s.Cs();
Transaction tx = session.beginTransaction();
try {
User u = new User();
u.setName("小巴");
u.setAge(18);
u.setPassword("aiweigege");
session.save(u);
tx.commit();
} catch (Exception e)
{
// TODO: handle exception
if(null!=tx){tx.rollback();}
e.printStackTrace();
}
finally
{
session.close();
}
}
@Test
public void updateTest()
{
Singleton s = Singleton.getInstance();
Session session = s.Cs();
Transaction tx = session.beginTransaction();
try {
User u = (User)session.get(User.class, new Integer(1));
u.setName("张三");
u.setAge(30);
u.setPassword("123456");
session.saveOrUpdate(u);
tx.commit();
} catch (Exception e) {
if(tx!=null)
{
tx.rollback();
}
e.printStackTrace();
}
finally
{
session.close();
}
}
@Test
public void testFind()
{
Singleton s = Singleton.getInstance();
Session session = s.Cs();
Transaction tx = session.beginTransaction();
try {
User u = (User) session.get(User.class, new Integer(1));
System.out.println(u);
tx.commit();
} catch (Exception e) {
if(tx!=null)
{
tx.rollback();
}
e.printStackTrace();
}
finally{
session.close();
}
}
@Test
public void testDeleteById()
{
Singleton s = Singleton.getInstance();
Session session = s.Cs();
Transaction tx = session.beginTransaction();
try {
User u = (User) session.get(User.class, new Integer(1));
session.delete(u);
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if(tx!=null)
{
tx.rollback();
}
e.printStackTrace();
}
finally
{
session.close();
}
}
}
静态代码块实现单态Session:
import org.User.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
class StaSingleton {
private static final Configuration config;
private static final SessionFactory factory;
static{
config = new Configuration().configure();
factory = config.buildSessionFactory();
}
//获取Session
public static Session getSession()
{
return factory.openSession();
}
}
public class TestStaSingleton
{
@Test
public void testIncrease(){
StaSingleton ss = new StaSingleton();
Session session = ss.getSession();
Transaction tx = session.beginTransaction();
try {
User u = new User();
u.setName("赵六");
u.setAge(18);
u.setPassword("woshizhaoliu");
u.setGender("男");
session.save(u);
tx.commit();
} catch (Exception e)
{
// TODO: handle exception
if(null!=tx){tx.rollback();}
e.printStackTrace();
}
finally
{
session.close();
}
}
@Test
public void updateTest()
{
StaSingleton ss = new StaSingleton();
Session session = ss.getSession();
Transaction tx = session.beginTransaction();
try {
User u = (User)session.get(User.class, new Integer(2));
u.setName("李四");
u.setAge(32);
u.setPassword("woshilisi");
u.setGender("男");
session.saveOrUpdate(u);
tx.commit();
} catch (Exception e) {
if(tx!=null)
{
tx.rollback();
}
e.printStackTrace();
}
finally
{
session.close();
}
}
@Test
public void testFind()
{
StaSingleton ss = new StaSingleton();
Session session = ss.getSession();
Transaction tx = session.beginTransaction();
try {
User u = (User) session.get(User.class, new Integer(1));
System.out.println(u);
tx.commit();
} catch (Exception e) {
if(tx!=null)
{
tx.rollback();
}
e.printStackTrace();
}
finally{
session.close();
}
}
@Test
public void testDeleteById()
{
StaSingleton ss = new StaSingleton();
Session session = ss.getSession();
Transaction tx = session.beginTransaction();
try {
User u = (User) session.get(User.class, new Integer(4));
session.delete(u);
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if(tx!=null)
{
tx.rollback();
}
e.printStackTrace();
}
finally
{
session.close();
}
}
}
部分功能演示:
数据库表截图:
在更新数据的时候发现报出了这样一个Error:
identifier of an instance of org.User.User was altered from 1 to 15
在网上找了一阵子还是没能发现到底错在哪里,最后仔细看了看自己的代码,发现是在更新操作的时候调用了实体类的setId()方法设置了id,将那一行删去之后便测试成功了,大家可不要像我一样粗心大意哦!