亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Hibernate基礎

系統 1910 0

Hibernate基礎
Part 1
1. 持久化對象
Event event = new Event();
// populate the event
Session session = factory.openSession();
session.save(event);
session.flush();
session.close();
當保存一個對象的時候,hibernate出于性能的考慮不會馬上將改對象寫到db。如果想要強制寫,就要用flush()方法。
經常將save和update合在一起使用,為saveOrUpdate()。Hibernate根據對象的id是null(或0),還是已經存在來判斷應該save還是update。
2. 讀取對象
根據id
Event event = (Event) session.load(Event.class, eventId);
session.close();
使用hql
Query query = session.createQuery("from Event");
List events = query.list();
3. 會話緩存session cache
出于性能的考慮,默認情況hibernate并不將一個操作立即反映到db中,而是做一些緩存的處理。
對一個會話期間的被load或save的每個對象,都能支持一個相應的緩存。
比如可以在一次會話中對對象a做load,update等多個處理,最后才flush提交,如
Session session = factory.openSession();
Event e = (Event) session.load(Event.class, myEventId);
e.setName("New Event Name");
session.saveOrUpdate(e);
// later, with the same Session instance
Event e = (Event) session.load(Event.class, myEventId);
e.setDuration(180);
session.saveOrUpdate(e);
session.flush();
緩存會帶來一些問題:
初學者容易犯NonUniqueObjectException,即在一個會話中對同一個對象做了不同步的操作,比如:
Session session = factory.openSession();
Event firstEvent = (Event) session.load(Event.class, myEventId);
// ... perform some operation on firstEvent
Event secondEvent = new Event();
secondEvent.setId(myEventId);
session.save(secondEvent);
可以看到secondEvent是一個與firstEvent同ID的對象,最后卻使用save,而不是update,顯然不對了。
對每個“經過”了會話的對象,都會被加到會話的緩存中。
“經過”的含義:保存對象,讀取對象。
session.contains()可以檢查某個對象是否在緩存中。
session.evict()可以將對象從緩存中清除。
session.clear()可以將所有對象從緩存清除。
Session session = factory.openSession();
Event firstEvent = (Event) session.load(Event.class, myEventId);
// ... perform some operation on firstEvent
if (session.contains(firstEvent)) {
session.evict(firstEvent);
}
Event secondEvent = new Event();
secondEvent.setId(myEventId);
session.save(secondEvent);
Part 2
1. 連接池connection pools
出于性能的考慮,不能為每一個到數據庫的請求,都給一個連接。而是使用連接池。
連接池保存了可以重用的一組到數據庫的連接。
應用服務器通常通過JNDI數據源datasource,提供自己的連接池支持,hibernate利用了服務器的這個特性。并且對沒有連接池支持的服務器也有相關支持,參見C3P0。
2. 事務
有的服務器支持簡單的JDBC事務,有的則能支持java transaction api(JTA)。
Jdbc和jta是兩種事務策略,到底使用哪種策略,可以在hibernate.cfg.xml設置。Jta的好處是可以允許你將多個獨立的事務當作一個事務對待。
在Hibernate中,對多個事務的處理是這樣的:
Transaction tx0 = session.beginTransaction();
Event event = new Event();
// ... populate the event instance
session.saveOrUpdate(event);
Transaction tx1 = session.beginTransaction();
Location location = new Location();
// ... populate the Location instance
session.saveOrUpdate(location);
tx0.commit();
tx1.commit();
上面,用一個會話創建了兩個事務,但是無論哪個事務的操作都會當作是第一個事務的操作來處理。顯然,是一個問題。(利用jta?)
<property name="transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
<property name="jta.UserTransaction">
java:comp/UserTransaction
</property>
當前,默認是使用jdbc的。
事務的一個示例:
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
Event event = new Event();
// ... populate the Event instance
session.saveOrUpdate(event);
tx.commit();
注意:這里沒有使用flush方法來強制將event寫入db,因為提交操作commit時會完成寫入。
Cache提供者provider
未完.........................................

Part 3 HQL
1. Hql具有properties:
Id和class
使用id可以引用對象的primary key,而不論你實際使用的是什么名字,例如:
from MyObject m where m.id > 50
查詢所有主健大于50的。
class是對象的完整java名字,如:
from Attendee a join a.payment p where p.class =
com.manning.hq.ch06.CashPayment
class屬性在對象樹結構中很有用。
2. 表達式
hql支持通常的sql表達式,比如:
size:返回子集合中的元素個數
from Event e where size(e.attendees) > 0
對有序集合:
支持的邏輯操作:
and, any, between, exists, in,
like, not, or, and some
支持的比較操作:
=, >, <, >=,
<=, and <>
3. 條件查詢criteria query
條件查詢為查詢提供了靈活性。當查詢參數的數目不定時,使用。
但是,條件查詢不支持聚集函數,并且只能得到這個對象,而不能只得到部分。
即,條件查詢沒有hql的全部功能,但是提高了靈活性。
兩種使用方式:
List results = session.createCriteria(Event.class).
.add( Restrictions.between("duration", new Integer(60),
new Integer(90) )
.add( Restrictions.like("name", "Presen%") )
.addOrder( Order.asc("name") )
.list();
以及:
Criteria criteria = session.createCriteria(Event.class);
criteria.add(Restrictions.between("duration",
new Integer(60), new Integer(90) );
criteria.add( Restrictions.like("name", "Presen%") );
criteria.addOrder( Order.asc("name") );
List results = criteria.list();
Part 4 利用spring和dao
1. Dao
為了將所有的hql(好處顯然:管理),有如下分解,將對象與db見加入一個專門處理持久化的對象dao。
可以為每一個類建立一個dao,可以為一個應用建立一個dao,建議前者。
簡單dao:
為具體對象承擔了如下責任:
每一個操作一個會話;
每一個操作一個事務,并負責打開和關閉事務;
處理異常;
客戶代碼不必考慮對象cast。
從Dao程序片斷體會上面的責任:
public class SimpleEventDao {
Log log = LogFactory.getLog(SimpleEventDao.class);
private Session session;
private Transaction tx;
public SimpleEventDao() {
HibernateFactory.buildIfNeeded();
}
public void delete(Event event)
throws DataAccessLayerException {
try {
startOperation();
session.delete(event);
tx.commit();
} catch (HibernateException e) {
handleException(e);
} finally {
HibernateFactory.close(session);
}
}
...
}
注意:其他真正的功能代碼只有一行session.delete(event),其他代碼被稱為excise稅,消費稅。編程時的內存管理是典型的稅代碼,java幫我們上了稅,程序員就用再管了。
2. 層次化的dao
其他的CRUD操作都是類似上面的結構,
因此:可以在簡單dao中不同的方法里看到結構和內容重復的代碼。
所以,需要簡化dao,見下:
將公共行為提取到父類。
父類中的delete片斷,可以對比前面的delete,區別只在參數一個是具體對象,一個是Object,而對象的cast問題就交給子類dao。
protected void delete(Object obj) {
try {
startOperation();
session.delete(obj);
tx.commit();
} catch (HibernateException e) {
handleException(e);
} finally {
HibernateFactory.close(session);
}
}
dao還要一些問題:因為每個操作一個會話,一個事務,因此一個按id號更新對象的過程,因為有兩個操作find和update,所以使用了兩個會話(每個會話又分別使用一事務)來完成,如下:
Event foundEvent = eventDao.find(event.getId());
foundEvent.setDuration(30);
eventDao.update(foundEvent);
但是,從效率上來說,一個會話,一個事務就可以了。
3. Spring的HibernateTemplate
Spring對hibernate的支持體現在為hibernate和重要的jdbc需求處理了資源管理稅代碼resource management excise。
前面談到dao中有重復代碼,重復代碼可以通過重構的手段解決,而dao中的重復代碼跟資源管理有關,因此Spring引入template來完成所有的資源處理部分,
Spring的HibernateTemplate幫我們完成了如下工作:
獲取會話,
開始事務,
處理異常,
顯式提交變化到db,
關閉會話。
可以看到,上面的流程就卻那個起到功能作用的方法(如CRUD了,因此dao中可以簡化為
protected void create(Event event) {
SessionFactory sf = HibernateFactory.getSessionFactory();
HibernateTemplate template = new HibernateTemplate(sf);
template.saveOrUpdate(event);
}
但是可以注意到上面的代碼還是使用的一個操作一個事務的模式。
有兩種方式與HibernateTemplate交互:
持久化方法和回調:
使用持久化方法的片斷:
SessionFactory sessionFactory =
HibernateFactory.getSessionFactory();
HibernateTemplate template =
new HibernateTemplate(sessionFactory);
Event event1 = new Event();
event1.setName("Event 1");
Event event2 = new Event();
event2.setName("Event 2");
try {
template.save (event1);
template.save (event2);
Event obj = (Event) template.load(Event.class,
event1.getId());
System.out.println("Loaded the event" + obj.getName());
List events = (List) template.find("from Event");
System.out.println("# of Events " + events.size());
} finally {
template.delete(event1);
template.delete(event2);
}
不是所有的操作(如非CRUD)都可以簡化為事務中的一個query。這時spring提供回調接口,寫將在HibernateTemplate中調用的回調函數。比如,有這樣一個操作根據一個復雜查詢的結果,更新結果集中的對象的屬性,最后保存。這是一個復雜的操作,要前面的CRUD是無法完成的,因此利用HibernateTemplate可以這樣做:
template.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query query = session.createQuery("from Event");
query.setMaxResults(2);
List events = query.list();
for (Iterator it = events.iterator(); it.hasNext();) {
Event event = (Event) it.next();
event.setDuration(60);
}
return null;
}
});
HibernateTemplate的接口就是一個實現doInHibernate方法的
HibernateCallback對象。
Execute方法以HibernateCallback對象為參數,應該還是替客戶代碼處理了資源處理稅代碼的。
4. Spring對java bean的配置和管理功能
Spring擅長配置和使用簡單的java bean。Spring可以做為一個工廠factory來配置和建造bean。
基于上面的功能,spring可以用來配置configure很多已存在的結構和類庫,比如hibernate。
Spring通過配置文件來管理bean。
配置文件指定了如何創建各種對象,包括Datasource,SessionFactory,所有的dao。
因此,可以從配置文件中:查找dao。
典型的spring配置文件ApplicaitonContext.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id=" dataSource "
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/events_calendar</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
<bean id=" factory "
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>com/manning/hq/ch07/Event.hbm.xml</value>
<value>com/manning/hq/ch07/Location.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id=" eventDao "
class="com.manning.hq.ch07.EventSpringDao">
<property name="sessionFactory">
<ref bean="factory" />
</property>
</bean>
</beans>
如上,來分析spring的配置文件:
1處利用Apache Commons database connection pool (DBCP)定義了使用的數據源,DBCP是在hibernate中集成了的。
2處利用spring內建的LocalSessionFactoryBean創建一個SessionFactory。并在3處連接到數據源。
4處配置dao,并在5處將dao連接到SessionFactory,這讓dao能夠打開會話,處理查詢。
Spring的applicationContext.xml可以替代hibernate的
hibernate.cfg.xml。
另外,有點spring比hibernate進步的地方:
對比前面的dao,在dao的構造函數中有這樣的代碼(來自hibernate quickly,其中HibernateFactory是hibernate quickly自己寫的。)
public SimpleEventDao() {
HibernateFactory.buildIfNeeded() ;
}
dao利用這段代碼會調用一個configureSessionFactory方法,根據hibernate的配置文件創建session,如下
private static SessionFactory configureSessionFactory() throws HibernateException {
Configuration configuration = new Configuration();
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
return sessionFactory;
}
spring中不需要用代碼顯式創建SessionFactory,只要讀
applicationContext.xml,其中有LocalSessionFactoryBean來處理創建
SessionFactory的問題。
結合下面的代碼和上面SimpleEventDao的構造器
Event event = new Event();
event.setName("A new Event");
EventDao eventDao = new EventDao();
eventDao.create(event);
可以看到:使用dao的步驟是,先創建dao對象,然后dao對象會創建SessionFactory。
Spring中不用顯示創建SessionFactory(這是第一點),
ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
EventSpringDao eventDao = (EventSpringDao) ctx.getBean("eventDao",
EventSpringDao.class);
Event event = new Event();
eventDao.saveOrUpdate(event);
注意:applicationContext.xml應該放在classpath里指定的path的root(似乎)。
總結一下就是:
在Hibernate中用戶代碼的責任:
創建dao對象,用new的方式,
dao對象創建SessionFactory對象,供dao中的CRUD操作使用。
而在spring中用戶代碼的責任:
創建dao對象,用getBean的方式(這似乎是一種create method方法,參見《重構與模式》中6.1《用Creation Method替換構造函數》)。
其實,上面提到“spring擅長配置和使用簡單的java bean”,所以使用上面代碼中的
ClassPathXmlApplicationContext.getBean()方法來完成。
Spring對層次化的dao的支持:
org.springframework.orm.hibernate3.support.HibernateDaoSupport。
其代碼:
public abstract class HibernateDaoSupport
implements InitializingBean {
protected final Log logger;
private HibernateTemplate hibernateTemplate;
public final void
setSessionFactory (SessionFactory sessionFactory);
public final SessionFactory getSessionFactory();
public final void
setHibernateTemplate(HibernateTemplate hibernateTemplate);
public final HibernateTemplate getHibernateTemplate();
protected final Session getSession ()
throws DataAccessResourceFailureException,
IllegalStateException;
protected final void closeSessionIfNecessary (Session session);
}
可以看到:HibernateDaoSupport的支持support體現在:
提供logger,以支持日志功能;
管理HibernateTemplate(有一個私有的hibernateTemplate);
管理SessionFactory(HibernateTemplate從HibernateAccessor繼承了SessionFactory);
上面的代碼雖然表明HibernateDaoSupport是抽象類,但是每個方式實際上有實現的(為什么?)。所以,關于SessionFactory,Session,HibernateTemplate的操作可以直接在客戶代碼中使用,而不用重載然后實現之。所以從該類繼承一個dao的話,可以簡化操作,如:
public abstract class AbstractSpringDao
extends HibernateDaoSupport{
public AbstractSpringDao() { }
protected void saveOrUpdate(Object obj) {
getHibernateTemplate().saveOrUpdate(obj);
}
protected void delete(Object obj) {
getHibernateTemplate().delete(obj);
}
protected Object find(Class clazz, Long id) {
return getHibernateTemplate().load(clazz, id);
}
protected List findAll(Class clazz) {
return getHibernateTemplate().find(
"from " + clazz.getName());
}
}
其實,上面的類已經是可以實例化的類了,不必標記為abstract。
上面的dao再被繼承為eventDao:一個dao應該有一個對應的session,dao的所有對數據庫的操作都要基于這個session里來完成(考察最初形式的dao可以看到Session類的變量),這個問題在配置文件中指明了一個SessionFactory來創建需要的Session:
<bean id="eventDao" class="com.manning.hq.ch07.EventSpringDao>
<property name="sessionFactory">
<ref bean="factory" />
</property>
</bean>
5. 集成spring對hibernate的支持,簡化代碼
下面用一個類來集成spring對hibernate的支持
public class CalendarRegistry {
private static ApplicationContext ctx;
static {
ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
}
private CalendarRegistry() {
}
public static SessionFactory getSessionFactory() {
return (SessionFactory) ctx.getBean(
"factory", SessionFactory.class);
}
public static EventSpringDao getEventDao() {
return (EventSpringDao)ctx.getBean(
"eventDao", EventSpringDao.class);
}
}
客戶代碼:
EventSpringDao eventDao = CalendarRegistry.getEventDao();
eventDao.saveOrUpdate(event);

Hibernate基礎


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 成人欧美一区二区三区黑人 | 欧洲精品视频在线观看 | 精品国产精品 | 人做人爱视频欧美在线观看 | 91福利国产在线观看一区二区 | 亚洲精品αv一区二区三区 亚洲精品爱爱久久 | 国产成人久久精品激情91 | 女人十八一级毛片 | 欧洲美女啪啪 | 天天狠狠弄夜夜狠狠躁·太爽了 | 中文字幕丝袜在线56页 | 国内高清久久久久久久久 | 番茄视频成人在线观看 | 91在线亚洲精品一区 | 国产在线精品一区二区高清不卡 | 99精品国产成人一区二区在线 | 91精品刘玥在线播放 | 日韩一区二区天海翼 | 亚洲成人99| 国产精品福利久久 | 亚洲美女激情视频 | 四虎成人免费网址在线 | 久久r这里只有精品 | 久久噜噜久久久精品66 | 成年女人色毛片免费 | 8090碰成年女人免费碰碰尤物 | 日韩日韩 | 久草视频首页 | 亚洲综合视频在线 | 女性下面全部视频免费 | 亚洲成a人片在线观看www | 爱我久久视频免费观看影视 | 精品久久久久久久久久久 | 色综合久久精品中文字幕 | 91精品视频在线看 | 国产伦理一区二区三区 | 亚洲视频在线播放 | 女人洗澡一级毛片一级毛片 | 四虎成人永久地址 | 成人看片免费无限观看视频 | 免费高清在线影片一区 |