- 浏览: 824772 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (488)
- struts1 (4)
- spring (13)
- extjs (36)
- mysql (3)
- sqlserver (2)
- oracle (37)
- 杂谈 (11)
- 面试相关 (35)
- Java基础知识总结 (5)
- Java重要知识点 线程和io流知识点 (6)
- 服务器相关 (1)
- 生活 (1)
- jsp (7)
- servlet (2)
- junit (3)
- struts2 (9)
- 开发必备 (4)
- 使用开发工具总结的知识 (4)
- ibatis (12)
- ajax (2)
- dwr (2)
- jquery (1)
- 设计模式 (4)
- Lucene的学习 (5)
- 经验总结 (19)
- mysql全文搜索相关 (7)
- hibernate (33)
- Sphinx (1)
- log4j的总结 (1)
- 敏捷开发 (9)
- 持续集成 (15)
- UML使用总结 (1)
- Scrum (1)
- OO(面向对象编程) (1)
- struts1和struts2总结 (1)
- 数据库加密 (1)
- 多线程和Socket编程 (6)
- PowerDesigner (2)
- 权限相关 (1)
- ant应用总结 (4)
- 面试必知知识点总结 (6)
- io流与nio流总结 面试相关 (1)
- 敏捷管理工具的使用 (7)
- hsqldb相关 (1)
- svn源码相关 (2)
- debug调试技巧总结 (1)
- hibernate和ibatis对比相关 (6)
- eclipse mylyn 插件的使用总结 (2)
- fisheye使用总结 (2)
- java泛型总结 (1)
- ssh整合总结 (10)
- SpringSide的学习总结 (1)
- JPA学习总结 (2)
- RoR 总结 (2)
- 模型驱动 总结 (1)
- Oracle SQL优化技巧 (4)
- 数据库相关资料 (1)
- oracle练习相关 (4)
- PowerDesigner 使用总结 (2)
- Struts实现国际化相关 (2)
- 权限框架 Spring Security (1)
- freemarker使用总结 (1)
- jsp servlet总结相关 (3)
- Java NIO总结 (1)
- 自己学习必须 (3)
- 蝴蝶容器相关 (2)
- eclipse插件的使用 (1)
- myeclipse的使用 (1)
- flex相关 (1)
- javaeye重生后总结的知识点 (2)
- 公司学习总结 (3)
- JAXB 相关 (1)
- ECSide (1)
- EdoJs 企业ajax框架 (1)
- RSA加密算法 (1)
- jbpm相关 (1)
- JMF原理 (1)
- MyEclipse使用总结 (1)
- Funsion Charts 相关总结 (3)
- 常用知识2011 (2)
- Flex与Java整合 (1)
- IBM WebSphere相关 (1)
- jQuery使用技巧 (2)
- 2011年面试相关知识点总结 (2)
- sqlserver开发相关 (8)
- eclipse 打jar相关 (2)
- Oracle/Mysql/SqlServer比较 (1)
- WebService Axis1.4开发相关 (4)
- 进制数的转换 总结 (1)
- WebService Axis2.0开发相关 (0)
- iteye Struts2 Spring Hibernate整合相关 (3)
- iteye osgi资料相关总结 (1)
- iteye ifos相关相关 (1)
- iteye 国际化相关 (1)
- iteye Hibernate缓存机制 (4)
- iteye Struts2 总结 (1)
- iteye Struts标签总结 (0)
- iteye web配置文件大全 (6)
- iteye Efs 框架总结 (1)
- iteye sql优化 (2)
- iteye 大数据量高并发的数据库优化 (1)
- iteye 开发相关 (1)
- iteye s1sh 和 s2sh整合中的问题以及解决 (1)
- iteye s1sh整合实例 (1)
- iteye s2sh整合实例 (1)
- iteye 面试相关 基础篇 (1)
- iteye Android相关 (1)
- iteye 面试相关 Web篇 (1)
- iteye Sql Server相关 (0)
- iteye struts1与struts2比较 (1)
- iteye jquery 和Struts2 (0)
- iteye struts2与其他插件整合 (0)
- iteye jquery 开发相关 (1)
- iteye eclipse结合spket(Ext,Jquery)开发相关 (0)
- iteye myeclipse 使用技巧相关 (0)
- iteye Memcached 缓存系统相关 (0)
- iteye 常用软件相关 (0)
- iteye 最新技术预览 AjaxSwing (0)
- iteye struts上传下载相关 (0)
- iteye 新技术相关 (0)
- test (0)
- iteye 开发Java游戏相关 (0)
- iteye Java反编译 (0)
- iteye XML解析相关 (0)
- iteye 压缩ZIP相关 (0)
- iteye 面试相关 (0)
- iteye Android开发相关 (4)
- csdn (0)
- e-inoc (0)
- iteye http错误码对应说明 (0)
- iteye 面试扩展知识点 (0)
- iteye oracle面试相关 存储过程,触发器,游标等 (0)
- iteye english study (0)
- iteye starflow工作流引擎 (0)
- iteye IBM WebSphere Application Server Toolkit使用相关 (0)
- iteye spring3 (0)
- iteye mybatis (0)
- iteye js技巧总结 (0)
- iteye SEO优化相关 (2)
- iteye QUI网页界面集成框架 (1)
- iteye AjaxAnywhere (1)
- iteye Nutz相关 (1)
- iteye ibatis技巧 (0)
- iteye dwz (0)
- 128个ajax/javascript框架 (0)
- iteye 2012 Java Swing教程 (1)
- iteye 码头集装箱相关 (1)
- iteye swing (2)
- 兼职工作 (0)
- 2012 新总结的面试相关知识点 常用知识点 (1)
- 淘宝网店相关 (0)
- oracle 常用函数 2012新总结 (1)
- 我的时尚潮流屋 (0)
- 2012 年 面试新总结知识 (1)
- 技巧 (1)
- 2013总结 (1)
- 2015工作相关 (3)
- springmvc (5)
- EasyPR-Java (1)
- java (2)
- editplus 4.0 注册码 (1)
- android (1)
- oracle连接数据库相关 (1)
- 编程资料总结 (2)
- 20160808 (1)
- visio 2013 (1)
最新评论
-
drew926:
泛型的类型参数可以有多个?这是java哪个版本支持的?
java泛型总结 -
listenan:
赞!非常感谢。
Scrum总结 -
cwscwj:
写的很深刻,谢谢,看了一遍,过段时间打算再看一遍。
Scrum总结 -
hwedwin:
w
Struts 2中的OGNL\EL的使用总结 -
lanni2460:
不错 很好 支持……
sqlserver三个驱动包下载
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);
/code]
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);
/code]
发表评论
-
Hibernate工作原理
2010-10-03 10:34 4098Hibernate工作原理 图 ... -
hibernate一对一映射外键关联
2010-09-17 11:24 1311hibernate一对一映射外键关联 一对一外键关联 外键关 ... -
在Hibernate中使用JDBC事务
2010-09-16 14:21 1285在Hibernate中使用JDBC事务 Hibernate ... -
hibernate事务,一级缓存,二级缓存
2010-09-16 12:34 1158hibernate主要从以下几个 ... -
Hibernate的五个核心接口介绍
2010-09-16 12:14 1005所有的Hibernate应用中都会访问Hibernate的 ... -
Hibernate缓存配置/批量处理
2010-09-16 12:01 1190Hibernate缓存配置/批量处 ... -
hibernate知识点总结
2010-09-16 08:48 1283hibernate知识点总结 1.hibernate的优缺点 ... -
项目缓存方案总结
2010-09-16 08:42 843项目缓存方案总结 一 ... -
hibernate缓存总结
2010-09-16 08:30 967hibernate缓存总结: 缓存是位于应用程序与 ... -
Hibernate中一级缓存、二级缓存及查询缓存的技术性总结
2010-09-15 22:54 869一、 一级缓存 1. 一级缓存只缓存整个对象 ... -
Hiberante3 一级缓存总结
2010-09-15 22:53 440Hiberante3 一级缓存总结 1. ... -
Hibernate中的缓存总结
2010-09-15 22:51 986Hibernate中的缓存总结 Hibernate ... -
hibernate缓存相关
2010-09-15 22:49 810hibernate缓存相关 hibernat ... -
hibernate技术面试相关
2010-09-13 20:51 1150Hibernate 中数据表映射关 ... -
hibernate 相关面试题
2010-09-13 20:50 10131.在数据库中条件查询 ... -
hibernate get()与load()的区别
2010-09-13 15:36 820hibernate get()与load()的区别 s ... -
Hibernate持久化对象的生命周期
2010-09-13 11:06 1053持久化对象的状态: ... -
Hibernate中持久化类实例的三种状态
2010-09-13 10:59 2130在Hibernate中持久化类实 ... -
全面介绍Hibernate持久化类
2010-09-13 10:55 1203Hibernate持久化类使用的是JavaBean的风格,为要 ... -
hibernate参考文档下载
2010-09-13 10:41 1174hibernate参考文档下载 这是一个非常有用改的hibe ...
相关推荐
【Hibernate 基础】是Java开发中一个重要的部分,主要关注如何将对象模型与关系数据库进行映射,以简化数据库操作。本PPT由传智播客制作,旨在帮助学习者掌握Hibernate的基础知识和应用。 首先,我们需要理解基于B/...
hibernate基础jar包。包含junit,antlr,don4j,hibernate-commons-annotations,hibernate-core,hibernate-jpa-api,javassit,jboss-logging,jboss-transaction-api
在本"Hibernate基础包"中,包含了用于SSH开发所需的全部核心库,使得开发者能够快速搭建项目并进行数据库交互。 首先,Hibernate的核心功能在于它的ORM(对象关系映射)机制。ORM允许开发者通过Java对象来操作...
本篇文章将深入探讨`Hibernate基础jar包`的构成,以及它们在Java Hibernate框架中的作用。 首先,Hibernate的核心jar包是实现ORM功能的基础。这些jar包包括但不限于以下: 1. **hibernate-core.jar**:这是...
本资源“Hibernate基础学习源码”提供了五个不同阶段的学习示例,分别命名为Hibernate_01至Hibernate_04以及Hibernate_M2M,涵盖了Hibernate的基本概念、配置、实体映射、CRUD操作以及多对多关系的处理。 1. **...
### Hibernate基础知识点详解 #### 一、什么是对象关系映射(ORM)以及为什么使用ORM? 在企业级应用开发中,持久层(persistence layer)占据了非常重要的地位。它主要负责处理与数据库之间的交互,包括数据的...
在本项目中,"springboot+hibernate基础项目"是一个使用Spring Boot和Hibernate框架构建的典型Java Web应用。Spring Boot简化了Spring的配置过程,而Hibernate则是一个强大的ORM(对象关系映射)工具,使得数据库...
**Hibernate基础知识** 1. **什么是Hibernate**:Hibernate是一个开源的Java ORM框架,它简化了Java应用与关系数据库之间的交互。通过提供一套API,Hibernate可以将Java对象自动持久化到关系数据库中,反之亦然,...
**Hibernate基础全攻略** Hibernate,一个强大的Java对象关系映射(ORM)框架,极大地简化了数据库操作,使得开发者可以专注于业务逻辑而不是繁琐的SQL代码。本篇攻略将深入探讨Hibernate的基础知识,帮助初学者...
**Hibernate 框架概述** Hibernate 是一个开源的对象关系映射(ORM)框架,它允许开发者用面向对象的方式来处理数据库操作。ORM 解决了在 Java 应用程序中使用传统 JDBC 进行数据库操作时遇到的繁琐代码问题,将...
### Hibernate基础知识点详解 #### 一、Hibernate简介与优势 **Hibernate** 是一款开源的对象关系映射(ORM)框架,它允许开发者以面向对象的方式来处理数据库操作,从而简化了Java应用与关系型数据库之间的交互。...
这个“Hibernate基础架包”包含了进行Hibernate开发所需的基本库文件,使得开发者可以快速地将其集成到自己的项目中,无需手动配置大量的依赖。 在Hibernate中,核心概念包括: 1. **实体(Entities)**:实体代表...
**Hibernate基础教程** Hibernate是一个强大的Java对象关系映射(ORM)框架,它简化了数据库与Java应用程序之间的数据交互。这个基础教程将引导我们逐步了解Hibernate的核心概念和使用方法。 **一、Hibernate概述*...
《Hibernate基础教程》是针对Java开发人员的一本经典教材,主要涵盖了如何使用Hibernate这一流行的ORM(对象关系映射)框架来简化数据库操作。配套代码包"Bh3 2nd Ed Source Code"则提供了实例代码,帮助读者更好地...