首先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,將那一行刪去之後便測試成功了,大家可不要像我一樣粗心大意哦!