`

hibernate ibatis n+1

阅读更多
当Hibernate或Ibatis在处理一对多的时候都存在n+1问题。
创建数据库
ACCOUNT 表
ACCOUNT_ID
1
2

ORDERS 表
ORDER_IDACCOUNT_ID
11
21
31
42
52
62

创建JavaBean
Account.java
public class Account {
	private Integer accountId;
	private Set<Orders> ordersSet = new HashSet<Orders>();
        // 省略 getter setter
        public String toString() {
		return "accountId:" + accountId;
	}
}

Orders.java
public class Orders {
	private Integer orderId;
	private Account account;
        // 省略getter setter
	public String toString() {
		return "orderId:"+orderId;
	}
}

一、使用Ibatis查询
SqlMapConfig.xml配置
<sqlMapConfig>
	<settings cacheModelsEnabled="true" enhancementEnabled="false"
		lazyLoadingEnabled="false" maxRequests="32" maxSessions="10"
		maxTransactions="5" useStatementNamespaces="true" />
	<transactionManager type="JDBC">  
        <dataSource type="SIMPLE">   
            <property name="JDBC.Driver" 
                      value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> 
            <property name="JDBC.ConnectionURL" 
                      value="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=TEST" /> 
            <property name="JDBC.Username" value="xiao" /> 
            <property name="JDBC.Password" value="xiao" /> 
        </dataSource> 
    </transactionManager>   
	<sqlMap resource="ibatis/n1.ibatis.xml" />
	<sqlMap resource="ibatis/groupby.ibatis.xml" />
</sqlMapConfig>

n1.ibatis.xml 配置
<sqlMap namespace="N1">
	<typeAlias alias="Account" type="bean.Account"/>
	<resultMap id="ResultAccountInfoMap" class="bean.Account">
		<result property="accountId" column="ACCOUNT_ID" />
		<result property="ordersSet" select="N1.getOrderInfoList" column="ACCOUNT_ID"/>
	</resultMap>
	<resultMap id="ResultOrderInfoMap" class="bean.Orders">
		<result property="orderId" column="ORDER_ID" />
		<result property="account.accountId" column="ACCOUNt_Id" />
	</resultMap>
	<select id="getAccountInfoList" resultMap="ResultAccountInfoMap">
		select account_Id from ACCOUNT 
	</select>
	<select id="getOrderInfoList" resultMap="ResultOrderInfoMap">
		select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = #value#
	</select>
</sqlMap>

groupby.ibatis.xml 配置
<sqlMap namespace="GroupBy">
	<resultMap id="ResultAccountInfoMap" class="bean.Account" groupBy="accountId">
		<result property="accountId" column="account_Id" />
		<result property="ordersSet" resultMap="GroupBy.ResultOrderInfoMap"/>
	</resultMap>
	<resultMap id="ResultOrderInfoMap" class="bean.Orders" groupBy="orderId">
		<result property="orderId" column="ORDER_ID" />
		<result property="account.accountId" column="ACCOUNT_ID" />
	</resultMap>
	<select id="getAccountInfoList" resultMap="ResultAccountInfoMap">
		 select 
		 ACCOUNT.ACCOUNT_ID AS ACCOUNT_ID
		,ORDERS.ORDER_ID AS ORDER_ID
		from ACCOUNT 
		join ORDERS on ACCOUNT.account_Id=ORDERS.ACCOUNT_ID
		group by ACCOUNT.ACCOUNT_ID,ORDERS.ORDER_ID
	</select>
</sqlMap>

测试代码
public static void queryN1() throws SQLException, IOException{
        Reader reader=Resources.getResourceAsReader("ibatis/SqlMapConfig.xml");
		SqlMapClient sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
		
		List<Account> accountList=sqlMapClient.queryForList("N1.getAccountInfoList");
		for(Account account:accountList){
			System.out.println("############"+account+"############");
			for(Orders orders:account.getOrdersSet()){
				System.out.println("############"+orders+"############");
			}
		}
}

执行以上代码,log4j打印如下:
[size=xx-small]2012-08-07 10:19:52,000-[HL] DEBUG main java.sql.Connection - {conn-100000} Connection
   2012-08-07 10:19:52,000-[HL] DEBUG main java.sql.Connection - {conn-100000} Preparing Statement:    select account_Id from ACCOUNT   
   2012-08-07 10:19:52,031-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Executing Statement:    select account_Id from ACCOUNT   
   2012-08-07 10:19:52,031-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Parameters: []
   2012-08-07 10:19:52,031-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Types: []
   2012-08-07 10:19:52,078-[HL] DEBUG main java.sql.Connection - {conn-100000} Preparing Statement:    select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = ?  
   2012-08-07 10:19:52,078-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100003} Executing Statement:    select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = ?  
   2012-08-07 10:19:52,078-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100003} Parameters: [1]
   2012-08-07 10:19:52,078-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100003} Types: [java.lang.Integer]
   2012-08-07 10:19:52,078-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100003} Executing Statement:    select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = ?  
   2012-08-07 10:19:52,078-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100003} Parameters: [2]
   2012-08-07 10:19:52,078-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100003} Types: [java.lang.Integer][/size][size=xx-small][/size]
   ############accountId:1############
############orderId:3############
############orderId:2############
############orderId:1############
############accountId:2############
############orderId:5############
############orderId:6############
############orderId:4############

查看以上log,发现执行了3条查询语句.
将SqlMapConfig.xml中的setting 节点中的lazyLoadingEnabled属性设为true
	<settings cacheModelsEnabled="true" enhancementEnabled="false"
		lazyLoadingEnabled="true" maxRequests="32" maxSessions="10"
		maxTransactions="5" useStatementNamespaces="true" />

再次执行之前queryN1测试代码,log4j打印如下
2012-08-07 10:26:42,468-[HL] DEBUG main java.sql.Connection - {conn-100000} Connection
   2012-08-07 10:26:42,468-[HL] DEBUG main java.sql.Connection - {conn-100000} Preparing Statement:    select account_Id from ACCOUNT   
   2012-08-07 10:26:42,515-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Executing Statement:    select account_Id from ACCOUNT   
   2012-08-07 10:26:42,515-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Parameters: []
   2012-08-07 10:26:42,515-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Types: []
   ############accountId:1############
2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.Connection - {conn-100003} Connection
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.Connection - {conn-100003} Preparing Statement:    select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = ?  
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100004} Executing Statement:    select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = ?  
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100004} Parameters: [1]
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100004} Types: [java.lang.Integer]
   ############orderId:3############
############orderId:1############
############orderId:2############
############accountId:2############
2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.Connection - {conn-100006} Connection
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.Connection - {conn-100006} Preparing Statement:    select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = ?  
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100007} Executing Statement:    select ORDER_ID,ACCOUNT_ID from ORDERS where ACCOUNT_ID = ?  
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100007} Parameters: [2]
   2012-08-07 10:26:42,562-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100007} Types: [java.lang.Integer]
   ############orderId:5############
############orderId:4############
############orderId:6############

查看log,依然有3条查询语句,只是查询的时机不一样了。当设置SqlMapConfig.xml中的setting 节点中的lazyLoadingEnabled属性设为true时(启动ibatis懒加载),ibatis会生成代理对对象,当集合元素真正使用时才执行查询语句(和hibernate类似)。
目前来看:至少在ibatis中启用或不启用懒加载,都不可以解决n+1问题.而在ibatis中使用groupby是一个解决方案.
测试代码如下:
	public static void queryGroupBy() throws SQLException, IOException{
        Reader reader=Resources.getResourceAsReader("ibatis/SqlMapConfig.xml");
		SqlMapClient sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
		List<Account> accountList=sqlMapClient.queryForList("GroupBy.getAccountInfoList");
		for(Account account:accountList){
			System.out.println("############"+account+"############");
			for(Orders orders:account.getOrdersSet()){
				System.out.println("############"+orders+"############");
			}
		}
	}

执行以上测试代码,log打印如下
2012-08-07 10:36:12,328-[HL] DEBUG main java.sql.Connection - {conn-100000} Connection
   2012-08-07 10:36:12,328-[HL] DEBUG main java.sql.Connection - {conn-100000} Preparing Statement:     select     ACCOUNT.ACCOUNT_ID AS ACCOUNT_ID   ,ORDERS.ORDER_ID AS ORDER_ID   from ACCOUNT    join ORDERS on ACCOUNT.account_Id=ORDERS.ACCOUNT_ID   group by ACCOUNT.ACCOUNT_ID,ORDERS.ORDER_ID  
   2012-08-07 10:36:12,359-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Executing Statement:     select     ACCOUNT.ACCOUNT_ID AS ACCOUNT_ID   ,ORDERS.ORDER_ID AS ORDER_ID   from ACCOUNT    join ORDERS on ACCOUNT.account_Id=ORDERS.ACCOUNT_ID   group by ACCOUNT.ACCOUNT_ID,ORDERS.ORDER_ID  
   2012-08-07 10:36:12,359-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Parameters: []
   2012-08-07 10:36:12,359-[HL] DEBUG main java.sql.PreparedStatement - {pstm-100001} Types: []
   ############accountId:1############
############orderId:3############
############orderId:2############
############orderId:1############
############accountId:2############
############orderId:4############
############orderId:6############
############orderId:5############

查看以上log,发现只有1条查询语句,解决了n+1问题。
目前看来,n+1问题算是解决了,可是配置文件搞得很复杂。
ibatis作为sql mapper并不是orm,非把ibatis当hibernate玩,个人认为这样并没有多大意义。

二 使用hibernate查询
hibernate.cfg.xml配置
<hibernate-configuration>
    <session-factory>
        <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
        <property name="connection.url">jdbc:sqlserver://127.0.0.1:1433;DatabaseName=TEST</property>
        <property name="connection.username">xiao</property>
        <property name="connection.password">xiao</property>
        <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <property name="show_sql">true</property>
        
    	<mapping resource="hibernate/Account.hibernate.xml"/>
    	<mapping resource="hibernate/Orders.hibernate.xml"/>
    </session-factory>
</hibernate-configuration>

Account.hibernate.xml 配置
<hibernate-mapping>
	<class name="bean.Account" table="ACCOUNT" >
		<id name="accountId" column="ACCOUNT_ID" />
		<set name="ordersSet" >
			<key column="ACCOUNT_ID"/>
			<one-to-many class="bean.Orders"/>
		</set>
	</class>
</hibernate-mapping>  

Orders.hibernate.xml 配置
<hibernate-mapping>
   <class name="bean.Orders" table="ORDERS">
	<id name="orderId" column="ORDER_ID"/>
	<many-to-one name="account" class="bean.Account" column="ACCOUNT_ID"/>
   </class>
</hibernate-mapping> 

a.hibernate 1对多 n+1
测试代码
	public static void query1(){
        Configuration config = new Configuration().configure("hibernate/hibernate.cfg.xml");  
        SessionFactory factory = config.buildSessionFactory();  
        Session session = factory.openSession();
        System.out.println("==========start query==========");
        Query query=session.createQuery("from Account as account");
        List<Account> accountList=query.list();
		for(Account account:accountList){
			System.out.println("############"+account+"############");
			for(Orders orders:account.getOrdersSet()){
				System.out.println("############"+orders+"############");
			}
		}
        session.close();
	}

执行以上测试代码,打印log如下:
   ==========start query==========
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_ from ACCOUNT account0_
############accountId:1############
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
############orderId:2############
############orderId:1############
############orderId:3############
############accountId:2############
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
############orderId:6############
############orderId:5############
############orderId:4############

查看以上log,发现3条查询语句。n+1 问题重现了。因为hibernate对集合查询默认是懒加载的,所以从以上打印log发现,只用在要使用集合时,hibernate才去执行查询。
将Account.hibernate.xml中set节点的lazy属性设置为false,如下
		<set name="ordersSet" lazy="false">
			<key column="ACCOUNT_ID"/>
			<one-to-many class="bean.Orders"/>
		</set>

再次执行query1()测试代码,log打印如下:
   ==========start query==========
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_ from ACCOUNT account0_
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
############accountId:1############
############orderId:1############
############orderId:3############
############orderId:2############
############accountId:2############
############orderId:5############
############orderId:4############
############orderId:6############

查看以上log,发现依然是3条查询语句,只是查询在一开始就全部执行了。
b.hibernate 多对1 n+1
测试代码
	public static void query2(){
		Configuration config = new Configuration().configure("hibernate/hibernate.cfg.xml");  
		SessionFactory factory = config.buildSessionFactory();  
		Session session = factory.openSession();
		System.out.println("==========start query==========");
		Query query=session.createQuery("from Orders");
		List<Orders> ordersSet=query.list();
		for(Orders orders:ordersSet){
			System.out.println("############"+orders+"############");
			System.out.println("############"+orders.getAccount()+"############");
		}
		session.close();
	}

执行以上测试代码,log如下:
   ==========start query==========
Hibernate: select orders0_.ORDER_ID as ORDER1_1_, orders0_.ACCOUNT_ID as ACCOUNT2_1_ from ORDERS orders0_
############orderId:1############
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_0_ from ACCOUNT account0_ where account0_.ACCOUNT_ID=?
############accountId:1############
############orderId:2############
############accountId:1############
############orderId:3############
############accountId:1############
############orderId:4############
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_0_ from ACCOUNT account0_ where account0_.ACCOUNT_ID=?
############accountId:2############
############orderId:5############
############accountId:2############
############orderId:6############
############accountId:2############

查看以上log,发现3条查询语句。
倘若将Account.hibernate.xml中set节点的lazy属性设置为false,如下
		<set name="ordersSet" lazy="false">
			<key column="ACCOUNT_ID"/>
			<one-to-many class="bean.Orders"/>
		</set>

再次执行query2(),log打印如下:
   ==========start query==========
Hibernate: select orders0_.ORDER_ID as ORDER1_1_, orders0_.ACCOUNT_ID as ACCOUNT2_1_ from ORDERS orders0_
############orderId:1############
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_0_ from ACCOUNT account0_ where account0_.ACCOUNT_ID=?
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
############accountId:1############
############orderId:2############
############accountId:1############
############orderId:3############
############accountId:1############
############orderId:4############
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_0_ from ACCOUNT account0_ where account0_.ACCOUNT_ID=?
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
############accountId:2############
############orderId:5############
############accountId:2############
############orderId:6############
############accountId:2############

查看以上log,发现5条查询语句。第一查询语句用来查询Orders信息,而Orders对象中的Account实例变量默认是懒加载的,所以当使用account变量时,hibernate才进行查询,由于Account对象中的ordersSet集合不启用懒加载。所以每次查询Account时会附带查询一次Orders.

c.hibernate 使用iterate n+1
测试代码
	public static void query3(){
		Configuration config = new Configuration().configure("hibernate/hibernate.cfg.xml");  
		SessionFactory factory = config.buildSessionFactory();  
		Session session = factory.openSession();
		System.out.println("==========start query==========");
		Query query=session.createQuery("from Account");
		Iterator<Account> iterator=query.iterate();
		while(iterator.hasNext()){
			Account account=iterator.next();
			System.out.println("############"+account+"############");
			System.out.println("############"+account.getOrdersSet()+"############");
		}
		session.close();
	}

执行以上测试代码,log打印语句如下:
   ==========start query==========
Hibernate: select account0_.ACCOUNT_ID as col_0_0_ from ACCOUNT account0_
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_0_ from ACCOUNT account0_ where account0_.ACCOUNT_ID=?
############accountId:1############
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
############[orderId:3, orderId:2, orderId:1]############
Hibernate: select account0_.ACCOUNT_ID as ACCOUNT1_0_0_ from ACCOUNT account0_ where account0_.ACCOUNT_ID=?
############accountId:2############
Hibernate: select ordersset0_.ACCOUNT_ID as ACCOUNT2_1_, ordersset0_.ORDER_ID as ORDER1_1_, ordersset0_.ORDER_ID as ORDER1_1_0_, ordersset0_.ACCOUNT_ID as ACCOUNT2_1_0_ from ORDERS ordersset0_ where ordersset0_.ACCOUNT_ID=?
############[orderId:6, orderId:5, orderId:4]############

查看以上log,发现有5条查询语句。第一条查询Account对象的accountId列表。当迭代使用Account时,hibernate会通过查询到的accountId在内存中找,如果找到则直接使用,如果为未找到则做一次查询。而把iterate查询归纳为n+1查询感觉不妥当,写在这里是想说明iterate没用好会产生n+1次查询或者更多。
如果将query3()中的迭代对象改为Orders,就会有很刺激的事,如果再将Account中的ordersSet懒加载去除(lazy=false),就更有意思了。
在hibernate中要解决n+1可以通过left join fetch。
将query1() 的hql该为from Account as account left join fetch account.ordersSet
重新执行则只有一条查询语句。

总结:不管是hibernate 还是ibatis 如果对象设计中有主从对象(主从对象指:一个对象中包含另一个对象,包含对象为主对象,被包含对象为从对象,从对象可为普通javabean或集合)都有可能碰到n+1问题,其中1指进行一条语句查询到n个主对象,而n指n个主对象要将从对象关联出来要进行n次查询。而解决方案不管怎样就是通过数据库join查询。而hibernate比较复杂点有很多缓存可用,所以具体的时候会有点差异。n+1并不是问题,更是一种策略。






分享到:
评论
1 楼 lijiejava 2012-08-08  
写的很不错!!!

相关推荐

    maven3+struts2+spring+ibatis

    maven3+struts2+spring+ibatis,本来是用maven3+struts2+spring+hibernate但考虑到hibernate在多表级联查询的时候执行效率不高,所以改用性能更好不过sql比较麻烦的的ibatis,本项目只有登录和插入数据,仅供参考: ...

    ibatis高级特性

    但 iBATIS 提供了两种方式来处理关联查询:N+1 次查询和新的查询方式。 1. **N+1 次查询** 这种方式在 SQL 映射文件中通过 `select` 属性指定一个单独的查询语句。虽然这种方法会导致额外的数据库读取操作,但可以...

    一个iBatis的demo

    10. **最佳实践**:分享一些使用 iBatis 的最佳实践,如避免N+1查询问题,提高性能的技巧等。 通过学习这个 iBatis 的 demo,开发者可以更好地理解和掌握 iBatis 在实际开发中的运用,提升数据访问层的构建能力。...

    ibatis spring

    支持代码生成工具,避免N+1查询问题。 - **缺点**:相较于Hibernate等框架来说,知名度和社区支持相对较低。 ### 3. 在具体项目中如何选择合适的技术栈 在实际项目开发过程中,选择合适的数据库访问技术是至关重要...

    iBATIS实战

    6.2.3 避免N+1查询问题 105 6.3 继承 107 6.4 其他用途 109 6.4.1 使用语句类型和DDL 109 6.4.2 处理超大型数据集 109 6.5 小结 115 第7章 事务 116 7.1 事务是什么 116 7.1.1 一个简单的银行转账示例 116 7.1.2 ...

    ibatis 开发指南

    8. **最佳实践与案例分析**:提供实际开发中的最佳实践,如如何优化SQL,避免N+1问题,以及在大型项目中如何有效地组织和管理映射文件。 9. **与其他框架集成**:探讨如何将iBatis与Spring、Struts等其他框架整合,...

    自己总结的IBATIS资料

    26. **避免N+1 Select(1:M和M:N)** - 在处理1:M或M:N关系时,同样需要考虑避免多次查询的问题。 27. **组合键值或多个复杂参数属性** - 可以通过组合键或多个参数属性来处理复杂的查询需求。 28. **缓存...

    hibernat培训.ppt

    6. **Hibernate最佳实践**:在使用Hibernate时,应注意避免过多的N+1查询,合理配置缓存策略,使用预编译的SQL语句(HQL或Criteria的CriteriaQuery),以及遵循事务管理的最佳实践,确保数据的一致性和完整性。...

    JAR包 整理说明

    但要注意性能优化,如避免过多的懒加载和N+1查询问题。 2. **iBatis**:适合对SQL有高度控制需求的项目,可以灵活地调整SQL语句,性能通常优于ORM框架。需要注意的是,SQL的维护和版本控制需要额外注意。 3. **JSON...

    高效使用JavaEE+ORM框架.pdf

    在JavaEE开发中,ORM(Object-Relational Mapping,对象关系映射)框架是...在处理大数据量或复杂业务逻辑时,还需注意优化查询,避免N+1查询问题,以及注意事务隔离级别和并发控制,确保系统的稳定性和数据的一致性。

    hibernat培训

    在使用Hibernate时,应遵循一些最佳实践,如合理设计实体关系,避免N+1查询问题,使用缓存提高性能,以及适当地处理事务。 总之,Hibernate培训的目标是让学员能够熟练掌握O/R Mapping的概念,灵活运用Hibernate...

    day66-mybatis面试题

    面试中可能会询问如何通过MyBatis进行SQL优化,包括使用合适的索引、避免N+1查询问题、合理使用缓存以及利用MyBatis提供的内置方法如foreach进行批量处理。 6. MyBatis与其他框架整合:MyBatis是一个轻量级的框架,...

    java文集

    ext学习笔记一 小试iBatis RIA(Rich Internet Application)的现状和未来 Java应用中域名解析不过期的解决方法 Java编程那些事儿45—数组使用示例1 一步步熟悉OFBiz 用Java做客户端调用.NET写...

    最新Java面试宝典pdf版

    11、iBatis与Hibernate有什么不同? 122 12、写Hibernate的一对多和多对一双向关联的orm配置? 122 9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么...

    MyBatis学习资料

    这种方式可能导致“1+N”查询问题,即查询一次主数据后,还需要为每条主数据执行N次子查询。 多对多映射示例: - 逻辑模型:一个User可以属于多个Group,一个Group也可以有多个User。 - XML配置中,通常需要中间表...

    JAVA面试宝典2010

    11、iBatis与Hibernate有什么不同? 122 12、写Hibernate的一对多和多对一双向关联的orm配置? 122 9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么...

    Java面试宝典-经典

    11、iBatis与Hibernate有什么不同? 122 12、写Hibernate的一对多和多对一双向关联的orm配置? 122 9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么...

    java面试宝典2012

    11、iBatis与Hibernate有什么不同? 133 12、写Hibernate的一对多和多对一双向关联的orm配置? 134 9、hibernate的inverse属性的作用? 134 13、在DAO中如何体现DAO设计模式? 134 14、spring+Hibernate中委托方案怎么...

Global site tag (gtag.js) - Google Analytics