﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-流浪的蜗牛-文章分类-Java框架</title><link>http://www.blogjava.net/vagasnail/category/42606.html</link><description>读历史、看小说、写程序都是我所爱。</description><language>zh-cn</language><lastBuildDate>Fri, 06 Nov 2009 13:41:41 GMT</lastBuildDate><pubDate>Fri, 06 Nov 2009 13:41:41 GMT</pubDate><ttl>60</ttl><item><title>Struts1.x的简单解读</title><link>http://www.blogjava.net/vagasnail/articles/301153.html</link><dc:creator>vagasnail</dc:creator><author>vagasnail</author><pubDate>Wed, 04 Nov 2009 13:13:00 GMT</pubDate><guid>http://www.blogjava.net/vagasnail/articles/301153.html</guid><wfw:comment>http://www.blogjava.net/vagasnail/comments/301153.html</wfw:comment><comments>http://www.blogjava.net/vagasnail/articles/301153.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vagasnail/comments/commentRss/301153.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vagasnail/services/trackbacks/301153.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1														、						Struts1.x														简单配置																																																a				）、配置				struts														       * 				拷贝				str...&nbsp;&nbsp;<a href='http://www.blogjava.net/vagasnail/articles/301153.html'>阅读全文</a><img src ="http://www.blogjava.net/vagasnail/aggbug/301153.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vagasnail/" target="_blank">vagasnail</a> 2009-11-04 21:13 <a href="http://www.blogjava.net/vagasnail/articles/301153.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring与Struts1.X的集成</title><link>http://www.blogjava.net/vagasnail/articles/301152.html</link><dc:creator>vagasnail</dc:creator><author>vagasnail</author><pubDate>Wed, 04 Nov 2009 13:12:00 GMT</pubDate><guid>http://www.blogjava.net/vagasnail/articles/301152.html</guid><wfw:comment>http://www.blogjava.net/vagasnail/comments/301152.html</wfw:comment><comments>http://www.blogjava.net/vagasnail/articles/301152.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vagasnail/comments/commentRss/301152.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vagasnail/services/trackbacks/301152.html</trackback:ping><description><![CDATA[
		<p>spring+struts的集成(第一种集成方案)<br />原理：在Action中取得BeanFactory对象，然后通过BeanFactory获取业务逻辑对象</p>
		<p>1、spring和struts依赖库配置<br /> * 配置struts<br />  --拷贝struts类库和jstl类库<br />  --修改web.xml文件来配置ActionServlet<br />  --提供struts-config.xml文件<br />  --提供国际化资源文件<br /> * 配置spring<br />  --拷贝spring类库<br />  --提供spring配置文件 <br />  <br />2、在struts的Action中调用如下代码取得BeanFactory<br /> BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());</p>
		<p>3、通过BeanFactory取得业务对象，调用业务逻辑方法   <br />  <br /> <br />spring+struts的集成(第二种集成方案)<br />原理：将业务逻辑对象通过spring注入到Action中，从而避免了在Action类中的直接代码查询</p>
		<p>1、spring和struts依赖库配置<br /> * 配置struts<br />  --拷贝struts类库和jstl类库<br />  --修改web.xml文件来配置ActionServlet<br />  --提供struts-config.xml文件<br />  --提供国际化资源文件<br /> * 配置spring<br />  --拷贝spring类库<br />  --提供spring配置文件 <br />2、因为Action需要调用业务逻辑方法，所以需要在Action中提供setter方法，让spring将业务逻辑对象注入过来</p>
		<p>3、在struts-config.xml文件中配置Action<br />  * &lt;action&gt;标签中的type属性需要修改为org.springframework.web.struts.DelegatingActionProxy<br />   DelegatingActionProxy是一个Action，主要作用是取得BeanFactory，然后根据&lt;action&gt;中的path属性值<br />   到IoC容器中取得本次请求对应的Action<br />   <br />4、在spring配置文件中需要定义struts的Action,如：<br /> &lt;bean name="/login" class="com.bjsxt.usermgr.actions.LoginAction" scope="prototype"&gt;<br />  &lt;property name="userManager" ref="userManager"/&gt;<br /> &lt;/bean&gt;<br /> * 必须使用name属性，name属性值必须和struts-config.xml文件中&lt;action&gt;标签的path属性值一致<br /> * 必须注入业务逻辑对象<br /> * 建议将scope设置为prototype,这样就避免了struts Action的线程安全问题<br />      <br />  <br />    <br /></p>
<img src ="http://www.blogjava.net/vagasnail/aggbug/301152.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vagasnail/" target="_blank">vagasnail</a> 2009-11-04 21:12 <a href="http://www.blogjava.net/vagasnail/articles/301152.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用iBatis</title><link>http://www.blogjava.net/vagasnail/articles/301150.html</link><dc:creator>vagasnail</dc:creator><author>vagasnail</author><pubDate>Wed, 04 Nov 2009 13:10:00 GMT</pubDate><guid>http://www.blogjava.net/vagasnail/articles/301150.html</guid><wfw:comment>http://www.blogjava.net/vagasnail/comments/301150.html</wfw:comment><comments>http://www.blogjava.net/vagasnail/articles/301150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vagasnail/comments/commentRss/301150.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vagasnail/services/trackbacks/301150.html</trackback:ping><description><![CDATA[
		<p>简介<br />使用SQL Map，能够大大减少访问关系数据库的代码。SQL Map使用简单的XML配置文件将Java Bean映射</p>
		<p>成SQL语句，对比其他的数据库持续层和ORM框架（如JDO的实现，Hibernate等），SQL Map最大的优点在</p>
		<p>于它简单易学。要使用SQL Map，只要熟悉Java Bean，XML和SQL，就能使您充分发挥SQL语句的能力。</p>
		<p>1.  com.ibatis.sqlmap.client.SqlMapClient<br /> 一个使用SQL Maps(从这个类开始运行的)的，线程安全的客户端。这个接口通过继承</p>
		<p>SqlMapTransactionManager和SqlMapExecutor接口获得了事务控制和执行方法。<br /> SqlMapClient是使用SQL Maps 的核心类。这个类将允许你映射操作语句(select、insert、</p>
		<p>update、delete等)，而且还划分了事务界线并能使用批处理。一旦你拥有了一个SqlMapClient实例，你</p>
		<p>使用SQL 映射变得足够简单。<br /> SqlMapClient能够直接作为多线程客户端使用(内部session管理)，或者你也能得到一个单线程</p>
		<p>的session并且使用它。如果你明确的获得一个session(使用 openSession()方法)的话，这里可能有一</p>
		<p>点轻微性能的提升，因为这样节省了SqlMapClient管理线程上下文信息的开销。但是在大多数的情况下</p>
		<p>，这不会产生什么不同，因此你可以选择任意一个你需要或喜欢的方式。<br /> 一个SqlMapClient实例可以被安全地作为静态的，或者实现为一个单例。一般来说，好的想法</p>
		<p>是，做成一个简单的配置类，而通过SqlMapClientBuilder去配置这个类的事例。<br /> 其实就是客户端程序员进行Sql Map操作的客户端类。<br />SQL Maps (com.ibatis.sqlmap.*) <br />SQL Map的概念<br />SQL Map API让开发人员可以轻易地将Java Bean映射成PreparedStatement的输入参数和ResultSet结果</p>
		<p>集。开发SQL Map的想法很简单：提供一个简洁的架构，能够用20％的代码实现80％JDBC的功能。<br />SQL Map如何工作？ <br />SQL Map提供了一个简洁的框架，使用简单的XML描述文件将Java Bean，Map实现和基本数据类型的包装</p>
		<p>类（String，Integer等）映射成JDBC的PreparedStatement。以下流程描述了SQL Maps的高层生命周期</p>
		<p>： <br />将一个对象作为参数（对象可以是Java Bean，Map实现和基本类型的包装类），参数对象将为SQL修改语</p>
		<p>句和查询语句设定参数值。<br />1) 执行mapped statement。这是SQL Maps最重要的步骤。SQL Map框架将创建一个PreparedStatement实</p>
		<p>例，用参数对象为PreparedStatement实例设定参数，执行PreparedStatement并从ResultSet中创建结果</p>
		<p>对象。<br />2) 执行SQL的更新数据语句时，返回受影响的数据行数。执行查询语句时，将返回一个结果对象或对象</p>
		<p>的集合。和参数对象一样，结果对象可以是Java Bean，Map实现和基本数据类型的包装类。</p>
		<p>
				<br /> 下面是使用SqlMapClient的示例代码：<br /> //<br /> // autocommit simple query --these are just examples...not patterns<br /> //<br /> <br /> Employee emp = (Employee) sqlMap.queryForObject("getEmployee", new Integer(1));<br /> <br /> //<br /> // transaction --these are just examples...not patterns<br /> //<br /> <br /> try {<br />   sqlMap.startTransaction()<br />   Employee emp2 = new Employee();<br />   // ...set emp2 data<br />   Integer generatedKey = (Integer) sqlMap.insert ("insertEmployee", emp2);<br />   emp2.setFavouriteColour ("green");<br />   sqlMap.update("updateEmployee", emp2);<br />   sqlMap.commitTransaction();<br /> } finally {<br />   sqlMap.endTransaction();<br /> }<br /> <br /> //<br /> // session --these are just examples...not patterns<br /> //<br /> <br /> try {<br />   SqlMapSession session = sqlMap.openSession()<br />   session.startTransaction()<br />   Employee emp2 = new Employee();<br />   // ...set emp2 data<br />   Integer generatedKey = (Integer) session.insert ("insertEmployee", emp2);<br />   emp2.setFavouriteColour ("green");<br />   session.update("updateEmployee", emp2);<br />   session.commitTransaction();<br /> } finally {<br />   try {<br />     session.endTransaction();<br />   } finally {<br />     session.close();<br />   }<br />   // Generally your session scope would be in a wider context and therefore the<br />   // ugly nested finally block above would not be there.  Realize that sessions<br />   // MUST be closed if explicitly opened (via openSession()).<br /> }<br /> <br /> //<br /> // batch --these are just examples...not patterns<br /> //<br /> <br /> try {<br />   sqlMap.startTransaction()<br />   List list = (Employee) sqlMap.queryForList("getFiredEmployees", null);<br />   sqlMap.startBatch ();<br />   for (int i=0, n=list.size(); i &lt; n; i++) {<br />     sqlMap.delete ("deleteEmployee", list.get(i));<br />   }<br />   sqlMap.executeBatch();<br />   sqlMap.commitTransaction();<br /> } finally {<br />   sqlMap.endTransaction();<br /> }</p>
		<p>
				<br /> </p>
<img src ="http://www.blogjava.net/vagasnail/aggbug/301150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vagasnail/" target="_blank">vagasnail</a> 2009-11-04 21:10 <a href="http://www.blogjava.net/vagasnail/articles/301150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的笔记</title><link>http://www.blogjava.net/vagasnail/articles/301149.html</link><dc:creator>vagasnail</dc:creator><author>vagasnail</author><pubDate>Wed, 04 Nov 2009 13:09:00 GMT</pubDate><guid>http://www.blogjava.net/vagasnail/articles/301149.html</guid><wfw:comment>http://www.blogjava.net/vagasnail/comments/301149.html</wfw:comment><comments>http://www.blogjava.net/vagasnail/articles/301149.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vagasnail/comments/commentRss/301149.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vagasnail/services/trackbacks/301149.html</trackback:ping><description><![CDATA[
		<p>1、 left outer join 左外连接：<br />左外连接的查询结果集中包括指定左表（主表）中的所有行，<br />* 而不仅仅是连接列的所有行。如果左表的某行在右表（从表）中没有找到匹配的行，则结果<br />       * 集中的右表的相对的位置为 NULL</p>
		<p>2、关于hibernate.hbm2ddl.auto<br />  &lt;property name="hibernate.hbm2ddl.auto"&gt;update&lt;/property&gt;<br />     将这个属性设为 update 只有我们发生修改的时候才会重新创建表 否则不会被覆盖掉（未理解）</p>
		<p>，在SessionFactory创建时，自动检查数据库结构，或者将数据库schema的DDL导出到数据库。使用 </p>
		<p>create-drop时,在显式关闭SessionFactory时，将drop掉数据库schema. <br />        例如：我们将所有的表都删除了当我们执行插入操作时，SessionFactory被创建那么会自动检</p>
		<p>查数据库scheme的DDL，建立数据表，并且会保留原来的数据，所以我们不用 Export 配置中的数据到数</p>
		<p>据库，那样会覆盖掉所有的数据。</p>
		<p>3、 关于对象关系信息导出<br />这里必须调用 configure 方法 否则会映射 properties 文件<br />        Configuration cfg = new Configuration().configure();  <br />  //用于导出用户定义的 xml 配置信息，在数据库中生成对应的Table<br />  SchemaExport export = new SchemaExport(cfg);<br />  export.create(true, true);</p>
		<p>4、* 测试lazy在class上的策略 这里默认为true <br />我们在这里应当搞清session.get()和session.load()的区别<br />方法load支持 lazy（在Session缓存中生成一个User的子类对象返回，只有当调用方法是才查询） 如果</p>
		<p>不存在查询的结果则抛异常<br />     session = HibernateUtil.getSession();<br />   tx = session.beginTransaction();<br />            Classes c1 = (Classes)session.load(Classes.class, 1);<br />            System.out.println("c1.getId()"+c1.getId());<br />            System.out.println("c1.getName()"+c1.getName());<br />这里不会发出sql语句，因为这里就采用lazy策略，所以这里采用了第三方的组件返回了一个,一个新的 </p>
		<p>Classes 的实例（代理），只有当我们需要查询属性时才会发出算sql语句,在这里不会发出sql语句因为</p>
		<p>id 是我们输入的。<br />hibernate 支持的lazy 策略只在session的生命周期内有效。</p>
		<p>5、lazy在collection上的策略<br /> 很显然这些lazy都是默认的<br />    Classes c1 = (Classes)session.load(Classes.class, 1);<br />   //如果我们将集合上的lazy设为false，这里会发出两条sql除了将要查询的</p>
		<p>普通属性查出来外，还会将非普通属性<br />   //将集合上的lazy设为extra和true是一样的<br />   System.out.println("c1.name= " + c1.getName());<br />   //没有发出sql 但是会生成一个 persistent 的set作为代理<br />            Set students = c1.getStudents();<br />            for(Iterator it = students.iterator();it.hasNext();){<br />             Student s = (Student)it.next();<br />             System.out.println("student.name= " + s.getName());<br />            }<br />            //System.out.println("student.number= " + student.size());<br />            //这里会将所有的数据读取出来并生成对象存放在set中<br />            /*这里Classes的lazy策略只对普通的属性有关，而collection的lazy策略才对<br />             * collection对象生效*/<br />*测试在标签上的lazy 策略和集合上的lazy策略一样。<br />6、one2one <br />&lt;class name="org.n2535.hibernate.Person" table="t_person"&gt;<br />  &lt;id name="id"&gt;<br />  &lt;!-- 这里表示了Person的主键是作为一个外键关联了IdCard的主键 --&gt;<br />     &lt;generator class="foreign"&gt;<br />     &lt;!-- 表示主键的生成是根据 属性 idCard 的 id --&gt;<br />       &lt;param name="property"&gt;idCard&lt;/param&gt;<br />     &lt;/generator&gt;<br />  &lt;/id&gt;<br />  &lt;property name="name" /&gt;<br />  &lt;!-- 表示了Person与Idcard是一对一的关系 默认为根据主键加载对象（主键关联） --&gt;<br />        &lt;!-- constrained(约束) (可选) 表明该类对应的表对应的数据库表，<br />               和被关联的对象所对应的数据库表之间，通过一个外键引用对主键进行约束。<br />              而且它们之间的约束条件为true<br />        在这里默认了两者的级联操作，否则的话一方的主键就为空没有任何意义了 --&gt;<br />  &lt;one-to-one name="idCard" constrained="true"/&gt;<br />&lt;/class&gt;<br />关于idCard的xml配置可以用<br />   &lt;!-- 默认为主键关联 即加载cardNo 时根据其主键将 关联的Person表中 主键相同的 元组</p>
		<p>取出<br />       默认的抓取策略为 Join  --&gt;<br />  &lt;one-to-one name="person"/&gt;</p>
		<p>当然也可以不用。</p>
		<p>7、extends<br /> &lt;!-- 测试每个具体的类映射一种表，这里Animal应该是抽象的，所以不应该被生成出来，将 </p>
		<p>abstract="true"--&gt;<br />&lt;class name="Animal" abstract="true"&gt;</p>
		<p>  &lt;id name="id"&gt;<br />     &lt;generator class="assigned"/&gt;<br />  &lt;/id&gt;<br />  &lt;!-- 此处不需要鉴别器，因为每个具体的类都生产了一张表 --&gt;<br />  &lt;property name="name" /&gt;<br />  &lt;property name="sex" /&gt;<br />  &lt;union-subclass name="Pig" table="t_pig"&gt;<br />  &lt;property name="weight"/&gt;<br />  &lt;/union-subclass&gt;<br />  <br />  &lt;union-subclass name="Bird" table="t_bird"&gt;<br />  &lt;property name="height"/&gt;<br />  &lt;/union-subclass&gt;<br /> &lt;/class&gt; </p>
		<p>&lt;!-- 测试单表继承映射 --&gt;<br />&lt;class name="Animal" table="t_animal" lazy="false"&gt;</p>
		<p>  &lt;id name="id"&gt;<br />     &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;!-- discriminator 鉴别器,用来识别不同的子类 --&gt;<br />  &lt;discriminator column="type" type="string"/&gt;<br />  <br />  &lt;property name="name" /&gt;<br />  &lt;property name="sex" /&gt;<br />  &lt;!-- Pig --&gt;<br />  &lt;!-- discriminator-value的默认是完整的类名 --&gt;<br />  &lt;subclass name="Pig" discriminator-value="P"&gt;<br />    &lt;property name="weight"/&gt;<br />  &lt;/subclass&gt;<br />  <br />  &lt;!-- Bird --&gt;<br />  &lt;subclass name="Bird" discriminator-value="B"&gt;<br />    &lt;property name="height"/&gt;<br />  &lt;/subclass&gt;<br /> &lt;/class&gt;</p>
		<p>8、component 组件映射测试<br /> component类不是一个实体类，在hibernate中的实体是指的 一个Pojo+一个映射文件<br />  component类是一个辅助类<br />   component 组件映射 <br />  &lt;component name="contact" class="org.n2535.hibernate.Contact"&gt;<br />    &lt;property name="email"/&gt;<br />    &lt;property name="address"/&gt;<br />    &lt;property name="zipCode"/&gt;<br />    &lt;property name="contactTel"/&gt;<br />  &lt;/component&gt;</p>
		<p>9、复合主键<br />因为主键是不可重复的，所以在复合主键的类中我们实现了Serializable接口，<br />和hashcode、equals方法，能够确保主键的唯一性。<br /> &lt;!-- 复合主键映射我们也可以认为是一种 component 组件映射的一种  --&gt;<br />   &lt;composite-id name="pk"&gt;<br />   &lt;key-property name="productYear"/&gt;<br />   &lt;key-property name="productMonth"/&gt;<br />   &lt;/composite-id&gt;<br />   &lt;property name="name"/&gt;<br />   &lt;property name="factory"/&gt;<br /> &lt;/class&gt; </p>
		<p>10、集合映射<br />   <br />  &lt;set name="setValue" table="t_set_value"&gt;<br />   &lt;key column="set_id"/&gt;<br />   &lt;element type="string" column="set_value"/&gt;<br />  &lt;/set&gt;<br />  <br />  &lt;list name="listValue" table="t_list_value"&gt;<br />   &lt;key column="list_id"/&gt;<br />   &lt;!-- 这里必须给出排序的索引，因为list是有序的（下同） --&gt;<br />   &lt;list-index column="list_index"/&gt;<br />   &lt;element type="string" column="list_value"/&gt;<br />  &lt;/list&gt;<br />  <br />  &lt;array name="arrayValue" table="t_array_value"&gt;<br />   &lt;key column="array_id"/&gt;<br />   &lt;list-index column="array_index"/&gt;<br />   &lt;element type="string" column="array_value"/&gt;<br />  &lt;/array&gt;<br />  <br />  &lt;map name="mapValue" table="t_map_value"&gt;<br />   &lt;key column="map_id"/&gt;<br />   &lt;map-key type="string" column="map_key"/&gt;<br />   &lt;element type="string" column="map_value"/&gt;<br />  &lt;/map&gt;</p>
		<p>11、关于Hibernate的锁<br /> 1）、悲观锁：先获得数据库的锁的线程，知道该线程放弃提交，其他的线程将无法修改该数据</p>
		<p>（LockMode.UPGRADE ：利用数据库的for update子句加锁。）<br />2）、乐观锁：通常利用一个 version 的版本冲突来实现，实际上不是数据库的锁，一个线程的version</p>
		<p>必须大于数据库中的version值才能被存储，否则报错。这样提供了比悲观锁宽松的条件，只要 version </p>
		<p>大于数据库中的version就可以被存储，而不会因为是否死一个线程先获得锁，因为乐观锁根本就不是一</p>
		<p>种锁。<br />  * 未使用悲观锁的时候，不同的操作可以访问相同的数据，那么会造成数据的错误<br />  * 使用悲观锁的时候，可以避免这个问题<br />可以不用显示的调用，如果为调用update那么在提交的时候会自动的update，当第一个操作将数据锁住</p>
		<p>的时候，（所有的其他访问将被禁止）第二个select操作将会阻塞，知道第一个操作释放了锁，第二个</p>
		<p>对象的选择操作会根据第一个对像的update的结果来读取数据，如果两个对象都从数据库中读取了相同</p>
		<p>的数据，那么第一次的update操作，将会被第二次的覆盖，造成错误的数据。<br /> session.update(inv);<br /> 要使用悲观锁请使用指定的数据库的命令，或者使用hibernate中的配置。<br />  * 乐观锁采用的version的冲突机制，如果update的version小于或数据库中的version<br />  * 将会产生错误插入失败，一位update的限制条件是根据 主键和version 所以会失败<br />  * 我们还能仿照 Hibernate 的乐观锁机制，用Jdbc实现乐观锁<br />  <br />12、hibernate查询语言hql <br />在hql中关键字不区分大小写，但是属性和类名区分大小写</p>
		<p>1)、简单属性查询【重要】<br /> * 单一属性查询，返回结果集属性列表，元素类型和实体类中相应的属性类型一致<br /> * 多个属性查询,返回的集合元素是对象数组,数组元素的类型和对应的属性在实体类中的类型</p>
		<p>一致<br />   数组的长度取决与select中属性的个数<br /> * 如果认为返回数组不够对象化，可以采用hql动态实例化Student对象<br /> 参见：SimplePropertyQueryTest.java  </p>
		<p>2)、实体对象查询【重要】<br /> * N + 1问题，在默认情况下，使用query.iterate查询，有可以能出现N+1问题<br />   所谓的N+1是在查询的时候发出了N+1条sql语句<br />   1: 首先发出一条查询对象id列表的sql<br />   N: 根据id列表到缓存中查询，如果缓存中不存在与之匹配的数据，那么会根据id发出相应的</p>
		<p>sql语句<br /> * list和iterate的区别？<br />  * list每次都会发出sql语句，list会向缓存中放入数据，而不利用缓存中的数据<br />  * iterate：在默认情况下iterate利用缓存数据，但如果缓存中不存在数据有可以能</p>
		<p>出现N+1问题<br /> 参见：SimpleObjectQueryTest1.java/SimpleObjectQueryTest2.java<br /> <br />3)、条件查询【重要】 <br /> * 可以采用拼字符串的方式传递参数<br /> * 可以采用 ？来传递参数（索引从0开始）<br /> * 可以采用 :参数名 来传递参数<br /> * 如果传递多个参数，可以采用setParamterList方法<br /> * 在hql中可以使用数据库的函数，如：date_format<br /> 参见：SimpleConditionQueryTest.java  <br />    <br />4)、hibernate也支持直接使用sql进行查询<br /> 参见：SqlQueryTest.java</p>
		<p>5)、外置命名查询<br /> * 在映射文件中采用&lt;query&gt;标签来定义hql<br /> * 在程序中采用session.getNamedQuery()方法得到hql查询串<br /> 参见：Student.hbm.xml、NameQueryTest.java<br /> <br />6)、查询过滤器 <br /> * 在映射文件中定义过滤器参数<br /> * 在类的映射中使用这些参数<br /> * 在程序中启用过滤器<br /> 参见：Student.hbm.xml、FilterQueryTest.java<br /> <br />7)、分页查询【重要】 <br /> * setFirstResult()，从0开始<br /> * setMaxResults,每页显示多少条数据<br /> 参见：PageQueryTest.java<br />     <br />8)、对象导航查询，在hql中采用 . 进行导航【重要】<br /> 参见：ObjectNavQueryTest.java<br /> <br />9)、连接查询【重要】<br /> * 内连<br /> * 外连接（左连接/右连接） <br /> 参见：JoinQueryTest.java<br /> <br />10)、统计查询【重要】<br /> 参见：StatQueryTest.java<br /> <br />11)、DML风格的操作（尽量少用，因为和缓存不同步）<br /> 参见：DMLQueryTest.java</p>
		<p>13、Hibernate中的缓存<br /> 1)、一级缓存<br />session 中一级缓存的生命周期和session的相同<br />由于load使用了session中的一级缓存 所以第二次的load 并不会发sql 因为在session的缓存中还存在</p>
		<p>相同的数据。<br />由于get使用了session中的一级缓存 所以第二次的get 并不会发sql 因为在session的缓存中还存在相</p>
		<p>同的数据。<br />    会发出查询 id 的 sql（使用一级缓存才会发出） 但是不会发出查询对象的 sql 因为Iterate</p>
		<p>查询支持缓存。<br />在save的时候会在缓存中保存一份当前对象的引用。<br />session.clear();//全部清除<br />2）、二级缓存<br />     &lt;!-- 指定二级缓存的提供者 --&gt;<br />    &lt;property name="cache.provider_class"&gt;org.hibernate.cache.EhCacheProvider&lt;/property&gt;<br />    &lt;!-- 指定是否使用二级缓存 默认为true --&gt;<br />&lt;property name="cache.use_second_level_cache"&gt;true&lt;/property&gt;<br />使用ehcache.xml这个配置文件来配置二级缓存。<br />session 中二级缓存的生命周期和sessionFactory的相同，所以又称为 sessionFactory 级缓存，二级</p>
		<p>缓存只能用于存储实体。<br />3）、三级缓存 <br />    &lt;!-- 使用查询缓存 默认为false--&gt;<br />    &lt;property name="cache.use_query_cache"&gt;true&lt;/property&gt;<br />queryCache生命周期和sessionFactory的相同。<br />但是在数据库里面的数据改变的时候，queryCache中的对象失效。<br />QueryCache的生命周期与session无关。<br />Iterate 接口不支持 QueryCache。<br />这里使用list 来查询实体对象 并开启了QueryCache 由于QueryCache 会存储实体的主键值，而list 在</p>
		<p>查询实体的时候不会使用缓存 所以list会使用QueryCache的实体的主键值 去查询相应的，实体，由于</p>
		<p>它会现在缓存中查找实体对象 如果不存在则会发出sql到数据库中查询 这里没有配置二级缓存 ，又重</p>
		<p>开了session所以在缓存中不存在实体对象 所以会根据在QueryCache 中的实体主键值发出sql到数据库</p>
		<p>中查询。<br />因为开启了二级缓存，QueryCache 会存储查询出来的实体的主键，而list会根据在QueryCache中的 主</p>
		<p>键值到二级缓存中查找相应的实体，所以不会发出sql（list接口不会使用一级缓存但是能够利用这种方</p>
		<p>法使用QueryCache 和 二级缓存）。</p>
		<p>14、抓取策略<br /> 1）、fetch = "select" 抓取策略 发两个select语句；fetch = "join" 抓取策略 使用外连接</p>
		<p>查询。<br />2）、在集合中的抓取策略<br /> •使用 load <br />  * fetch = "select" 抓取策略 发两条sql<br />  * fetch = "join" 发一条sql 采用外连接查询<br />•使用 HQL <br />* fetch = "select" 抓取策略 发两条sql 和加载对象方式一样,每次每个实体的集合时会发sql <br />* fetch = "subselect" 将会在查询实体的集合时将所有查询的实体的集合发一次sql 全部查询出来<br />3）、测试 batch – size<br /> batch-size="3"在集合中设置。</p>
		<p> </p>
<img src ="http://www.blogjava.net/vagasnail/aggbug/301149.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vagasnail/" target="_blank">vagasnail</a> 2009-11-04 21:09 <a href="http://www.blogjava.net/vagasnail/articles/301149.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>