Mybatis哲学

来源:互联网 发布:淘宝商品降权3天恢复 编辑:程序博客网 时间:2024/05/22 17:05

     MyBatis上层接口使用简单工厂模式,核心接口为org.apache.ibatis.session.SqlSession。其中定义了与数据相关的所有操作,以及和MyBatis本身相关的几个方法,比如getConfiguration和getMapper。下图列出了部分常用方法:


    
     从上面的类图中可以看出,SqlSession已经覆盖了DAO模式中的所有方法。因为是ORM框架,所以都是包装方法。但如果在特殊情况下,一定要用JDBC原始java.sql.Connection接口的话,SqlSession中也提供了getConnection这个方法来获取。可以想象,这只有在很特别的情况下才会用到,因为此后,你对java.sql.Connection所做的任何操作都与MyBatis无关了,它提供的所有功能也因此不再有效,如事务等,都需要自己手动来管理了。

     上面提到,MyBatis的上层核心接口是SqlSession,因此,上层的其它接口和类,均围绕它展开。下面从一个官方应用指南中的经典API例子开始,引出这几个重要的类。

点击(此处)折叠或打开

  1. String evironment="development";
  2. InputStream is = getClass().getResourceAsStream("/SqlMapperConfig.xml");
  3. SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
  4. SqlSessionFactory factory = factoryBulider.bulid(is,evironment);
  5. SqlSession session = factory.openSession();
  6. String selectId = "test.foo";
  7. Object bean = session.selectOne(selectdId);
  8. session.close;
   这是一个简单的查询,涉及到下面这几个类,它们是使用的MyBatis的入口:
  • org.apache.ibatis.session.SqlSessionFactoryBuilder : SQL会话工厂的构建类
  • org.apache.ibatis.session.SqlSessionFactroy : 打开一个SQL会话的工厂类
  • org.apache.ibatis.session.SqlSession : SQL会话本身
  • org.apache.ibatis.session.Configuration : 整个MyBatis的配置
   似乎有点太简单了,其实不然,这只是入口。关键的地方是SqlSessionFactory这个接口的实例是如何被创建出来的呢?显然答案就在SqlSessionFactoryBuilder这个默认实用类中。另外,org.apache.ibaits.session.Configuration这个类是怎么冒出来的呢?答案也在SqlSessionFactoryBuilder的实现代码里,那还等什么,源码List出来吧:

点击(此处)折叠或打开

  1. public class SqlSessionFactoryBuilder {
  2.   public SqlSessionFactory build(Readerreader){
  3.     return build(reader,null,null);
  4.   }
  5.   
  6.   public SqlSessionFactory build(Readerreader,Stringenvironment){
  7.     return build(reader,environment,null);
  8.   }
  9.   
  10.   public SqlSessionFactory build(Readerreader,Propertiesproperties){
  11.     return build(reader,null,properties);
  12.   }
  13.   
  14.   public SqlSessionFactory build(Readerreader,Stringenvironment,Propertiesproperties){
  15.     try {
  16.       XMLConfigBuilder parser = new XMLConfigBuilder(reader,environment,properties);
  17.       return build(parser.parse());
  18.     } catch(Exception e){
  19.       throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  20.     } finally{
  21.       ErrorContext.instance().reset();
  22.       try {reader.close();catch(IOException e){//Intentionally ignore. Prefer previous error.}
  23.     }
  24.   }

  25.   public SqlSessionFactory build(InputStreaminputStream){
  26.     return build(inputStream,null,null);
  27.   }

  28.   public SqlSessionFactory build(InputStreaminputStream,Stringenvironment){
  29.     return build(inputStream,environment,null);
  30.   }

  31.   public SqlSessionFactory build(InputStreaminputStream,Propertiesproperties){
  32.     return build(inputStream,null,properties);
  33.   }

  34.   public SqlSessionFactory build(InputStreaminputStream,Stringenvironment,Propertiesprops){
  35.     try {
  36.       XMLConfigBuilder parser = new XMLConfigBuilder(inputStream,environment,props);
  37.       return build(parser.parse());
  38.     } catch(Exception e){
  39.       throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  40.     } finally{
  41.       ErrorContext.instance().reset();
  42.       try{inputStream.close();}catch(IOException e){//Intentionally ignore.Prefer previous error.}
  43.     }
  44.   }
  45.     
  46.   public SqlSessionFactory build(Configurationconfig){
  47.     return new DefaultSqlSessionFactory(config);
  48.   }
  49. }
   从它的类签名和构造方法签名就可以看出,这个类是即用即扔的,正好与MyBatis源码赏析一中提到的生命周期相吻合。这个类只有一个方法,就是build。build方法被重载(overide)了多次,可分为三组:
  1. 通过指定org.apache.ibais.session.Configuration来构建DefaultSqlSessionFactory
  2. 从一个Reader中加载Configuration,并构建SqlSessionFactory
  3. 从一个Stream中加载Configuration,并构建SqlSessionFactory
  2和3又被重载了多次,但最终,这两类build方法的任务都是从不同的源加载配置,而SqlSessionFactory具体的构建过程,则委托给1类这个build方法。由此可见,SqlSessionFactoryBuilder这个类,其实也没做什么,只是从不同的源加载配置,为编程提供入口。而具体的加载过程都委托给了其它类。

  从SqlSessionFactoryBuilder中构建出来的工厂实现类,都是DefaultSqlSessionFactory,这是MyBatis默认的SqlSessionFactory接口的实现类,也是唯一一个真实的实现类,在本文的版本中(3.0.6),还有另外一个实现类:SqlSessionManager,但它并不是一个功能上的实现类,而是对SqlSession在实际应用开发过程中的实用工具类。因此,现在的重点落在了DefaultSqlSessionFactory类。SqlSessionFactory的功能是负责打开一个连接会话,该接口只定义了两个方法如下:

点击(此处)折叠或打开

  1. public interface SqlSessionFactory {
  2.   SqlSession openSession();

  3.   SqlSession openSession(boolean autoCommit);
  4.   SqlSession openSession(Connectionconnection);
  5.   SqlSession openSession(TransactionIsolationLevellevel);

  6.   SqlSession openSession(ExecutorType execType);
  7.   SqlSession openSession(ExecutorType execType,boolean autoCommit);
  8.   SqlSession openSession(ExecutorType execType, TransactionIsolationLevellevel);
  9.   SqlSession openSession(ExecutorType execType,Connectionconnection);

  10.   Configuration getConfiguration();
  11. }
  可以看出,主要就是openSession方法,通过重载多次,来得到不同的会话特性。再看看DefaultSqlSessionFactory是如何实现openSession这个方法的。这儿就不贴出源码了,所有的openSession方法最终通过转调两个方法来实现的,分别是openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level,boolean autoCommit)和openSessionFromConnection(ExecutorType execType, Connection connection),这样做显然是因为SqlSessionFactory接口的openSession方法签名就被这样分成了两类,FromDataSource这一类的,显然是通过DataSource来获取java.sql.Connection的,FromConnection则是直接指定Connection的。这里我们可以看出,这样做的目的在最高层提供了灵活性,也是手工编程的入口。虽然我们实际开发过程中,都是通过配置xml的方式来使用MyBatis的。但了解到这些后,为我们自己扩展MyBatis提供了入口。
 
  现在还剩下一个问题,前面提到的几个高层接口都找到了相应的实现类,那SqlSession呢?它的实现类是什么?当然你用Eclipse或是NetBeans这些高级IDE可以一下子找到,不过,我们这儿另辟溪径。我们知道,一个SqlSession的实例是这样得到的:SqlSessionFactoryBuilder.build(...).openSession(...);而build方法返回的是DefaultSqlSessionFactory实现类,查看一下这它的openSession方法不就知道了么。是的,如前段所述,最终我们可以在openSessionFromDataSource和openSessionFromConnection这两个方法中找到,得到的SqlSession实现类是org.apache.ibatis.session.defaults.DefaultSqlSession。再进入到该类中,在这儿,我们就快要接近真相(我们想知道,SqlSession的CRUD操作是如何实现的)了。其实,具体CRUD操作,都委托给了org.apache.ibaits.executors.Executor接口了。DefaultSqlSession只是为Executor提供执行参数和环境,是一个管理者,下面是它开头的部分源码:

点击(此处)折叠或打开

  1. public class DefaultSqlSession implements SqlSession{

  2.   private Configurationconfiguration;
  3.   private Executorexecutor;

  4.   private boolean autoCommit;
  5.   private booleandirty;

  6.   public DefaultSqlSession(Configurationconfiguration,Executorexecutor,boolean autoCommit){
  7.     this.configuration=configuration;
  8.     this.executor=executor;
  9.     this.autoCommit= autoCommit;
  10.     this.dirty= false;
  11.   }
  12.   ....
  13. }
  可以看出,它主要管理维护两个类实例,分别是Executor和Configuration。顾名思义,前者负责执行,后者负责提供数据,而SqlSession本身则身负将二者关联起来,加以管理。

  通过前面的分析,我们大致可以得到MyBatis一个粗略的上层架构类图:

  作为一名一线应用开发人员,“配置”一词,可能已经听得耳朵都长茧了。但是,一个程序或者说是一个库,具有可配置性,是非常必要的,否则就得以纯编程的方式使用它们。试想一下,如果你在使用数据库产品时,你还需要通过编程来使用,那将是多么地糟糕!

     配置不仅仅是使用的人要用,这个库或者框架的开发者自己也需要用,否则,如何组织内部的各个构件,将会是一件硬编码的事情。总之,配置,就是要组织出一个完整的逻辑或形式系统,以达到使用者的目的。在框架内部来说,通过配置,还在看清楚整个架构。

     通过MyBatis的配置,可以看出整个框架的顶级特性。为什么这么说呢,把这些代码列出来就一目了然了。

点击(此处)折叠或打开

  1. public class Configuration {

  2.   protected Environmentenvironment;

  3.   protected boolean safeRowBoundsEnabled= true;
  4.   protected boolean mapUnderscoreToCamelCase= false;
  5.   protected boolean lazyLoadingEnabled= false;
  6.   protected boolean aggressiveLazyLoading= true;
  7.   protected boolean multipleResultSetsEnabled= true;
  8.   protected boolean useGeneratedKeys= false;
  9.   protected boolean useColumnLabel= true;
  10.   protected boolean cacheEnabled= true;
  11.   protected Integer defaultStatementTimeout;
  12.   protected ExecutorType defaultExecutorType= ExecutorType.SIMPLE;
  13.   protected AutoMappingBehavior autoMappingBehavior= AutoMappingBehavior.PARTIAL;

  14.   protected Properties variables=newProperties();
  15.   protected ObjectFactoryobjectFactory=new DefaultObjectFactory();
  16.   protected ObjectWrapperFactory objectWrapperFactory=new DefaultObjectWrapperFactory();
  17.   protected MapperRegistry mapperRegistry = new MapperRegistry(this);

  18.   protected final InterceptorChain interceptorChain=new InterceptorChain();
  19.   protected final TypeHandlerRegistry typeHandlerRegistry=new TypeHandlerRegistry();
  20.   protected final TypeAliasRegistry typeAliasRegistry=new TypeAliasRegistry();
  21.   protected finalMap<String, MappedStatement> mappedStatements= new StrictMap<String, MappedStatement>("Mapped Statements collection");
  22.   protected finalMap<String, Cache> caches= new StrictMap<String, Cache>("Caches collection");
  23.   protected finalMap<String, ResultMap> resultMaps= new StrictMap<String, ResultMap>("Result Maps collection");
  24.   protected finalMap<String, ParameterMap> parameterMaps= new StrictMap<String, ParameterMap>("Parameter Maps collection");
  25.   protected finalMap<String,KeyGenerator> keyGenerators= new StrictMap<String,KeyGenerator>("Key Generators collection");

  26.   protected finalSet<String> loadedResources=newHashSet<String>();
  27.   protected finalMap<String, XNode> sqlFragments= new StrictMap<String, XNode>("XML fragments parsed from previous mappers");

  28.   protected finalCollection<XMLStatementBuilder> incompleteStatements=newLinkedList<XMLStatementBuilder>();
  29.   protected finalCollection<CacheRefResolver> incompleteCacheRefs=newLinkedList<CacheRefResolver>();
  30.   protected finalCollection<ResultMapResolver> incompleteResultMaps=newLinkedList<ResultMapResolver>();
  31.   /**
  32.    * A map holds cache-ref relationship. The key is the namespace that
  33.    * references a cache bound to another namespace and the value is the
  34.    * namespace which the actual cache is bound to.
  35.    */
  36.   protected finalMap<String,String> cacheRefMap= newHashMap<String,String>();

  37.   public Configuration(Environmentenvironment){
  38.     this();
  39.     this.environment=environment;
  40.   }

  41.   public Configuration(){
  42.     typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class.getName());
  43.     typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class.getName());
  44.     typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class.getName());
  45.     typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class.getName());
  46.     typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class.getName());

  47.     typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class.getName());
  48.     typeAliasRegistry.registerAlias("FIFO", FifoCache.class.getName());
  49.     typeAliasRegistry.registerAlias("LRU", LruCache.class.getName());
  50.     typeAliasRegistry.registerAlias("SOFT", SoftCache.class.getName());
  51.     typeAliasRegistry.registerAlias("WEAK", WeakCache.class.getName());
  52.   }

  53. ......
  54. }
    通过这些字段的名字,我们就可以知道,MyBatis所支持的顶级特性了。之所以叫顶级特性,是因为这些字段出现在顶级配置中,其它一些边缘特性则隐藏在各个字段的实现里。当然,有些不能叫做特性,而应该叫基本术语或基础概念。对应上面的字段,下面列出这些特性或术语:

     数据环境(包括数据源和事务)
     是否启用严格的行绑定
     是否启用下划线与驼峰式命名规则的映射(如first_name => firstName)
     是否启用懒加载模式
     是否启用贪婪地懒加载模式(即尽可能多地使用懒加载)
     是否启用多结果集映射
     是否启用主键生成功能
     是否启用采用列标签功能(如果不启用,则使用下标索引)
     是否启用缓存功能
     默认的JDBC语句超时设置
     默认的执行器类型(共有SIMPLE,REUSE和BATCH三种)
     初始化SqlMapping自动映射行为(共有NONE,PARTIAL和FULL三种)
    
     其它文本属性(作为扩展或使用者自己用,存放在Promerties中)
     初始化生成对象(实例)的工厂
     初始化对象的包装工厂(用于代理,完成一些重要的特性,比如事务)
     初始化SqlMapping的映射器
    
     初始化拦截器链
     初始化类型处理注册器(默认的注册器就已经预注册了常见的类型)
     初始化类型别名注册器
     初始化JDBC语句容器(就是一个Map,下同)
     初始化缓存
     初始化结果集容器
     初始化参数容器
     初始化主键生成器容器
    
     初始化化已经加的载资源容器
     初始化SQL语句片断容器(SQL语句片断,是可重用的,相信大家在Mapping文件中经常用到)
    
     初始化不完整的JDBC语句容器(显然这个语句还没有执行插值操作)
     初始化不完整的缓存引用容器
     初始化不完整的结果集映射容器
    
     初始化缓存引用容器
     ----------------------------------------------------

     Configuration默认有两个构造器,一个是无参的,另一个则需要指定数据环境。但指定数据环境的这个构造器首先调用了无参的构造器。通过上面的源码,我们可以看到,无参构造器主要是注册了一些重要的类型别名,这些别名在XML配置中会用到。整个Configuration的所有字段都已经初始化了,除了environmnet。因此,它还提供一个传递数据环境的构造器。
    
      Configuration是所有组件的有机组合器,同时也是运行时数据收集器,它会在DefaultSqlSession中用到,并再次传递给Executor接口,它们都依赖它。可以说它是拼接整个MyBatis应用的核心人物,就像Spring在应用程序开发中的地位。

summary:

MyBatis3中实现一对多的查询比较简单,可以自动完成。但插入操作要复杂一些,需要相关的DAO配合完成,这点不如Hibernate。


场景描述:

类:Mail和Attachment类

关系描述:一封邮件(Mail)可以有0个或多个附件(Attachment),附件(Attachment)仅对应一封邮件。

表格:mail表(主键:id_mail)和attachment表(外键:id_mail)。


POJO:Mail.java
[java] view plaincopyprint?
  1. public class Mail implements Serializable {  
  2.     private static final long serialVersionUID = 7427977743354005783L;  
  3.     private Integer id;  
  4.     private String sender;  
  5.     private String subject;  
  6.     private String content;  
  7.     private String fromAddress;  
  8. ...  
  9. getters and setters...  
  10. }  
public class Mail implements Serializable {private static final long serialVersionUID = 7427977743354005783L;private Integer id;private String sender;private String subject;private String content;private String fromAddress;...getters and setters...}
Attachment.java
[java] view plaincopyprint?
  1. public class Attachment implements Serializable {  
  2.     private static final long serialVersionUID = -1863183546552222728L;  
  3.     private String id;  
  4.     private String mailId;  
  5.     private String name;  
  6.     private String relativePath;  
  7. ...  
  8. getters and setters...  
  9. }  
public class Attachment implements Serializable {private static final long serialVersionUID = -1863183546552222728L;private String id;private String mailId;private String name;private String relativePath;...getters and setters...} SqlMapConfig:
[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">  
  3. <configuration>  
  4.     <properties resource="test/properties/mysql.properties"></properties>  
  5.       
  6.     <typeAliases>  
  7.         <typeAlias type="test.model.Mail" alias="Mail"/>  
  8.         <typeAlias type="test.model.Attachment" alias="Attachment"/>        
  9.     </typeAliases>  
  10.       
  11.       
  12.     <environments default="development">  
  13.         <environment id="development">  
  14.             <transactionManager type="JDBC" />  
  15.             <dataSource type="UNPOOLED">  
  16.                 <property name="driver" value="${db_driver}" />  
  17.                 <property name="url" value="${db_url}" />  
  18.                 <property name="username" value="${db_user}" />  
  19.                 <property name="password" value="${db_password}"/>  
  20.             </dataSource>  
  21.         </environment>  
  22.     </environments>    
  23.           
  24.     <mappers>  
  25.     <mapper resource="test/data/MailMapper.xml"/>  
  26.     <mapper resource="test/data/AttachmentMapper.xml"/>  
  27.     </mappers>      
  28. </configuration>  
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><properties resource="test/properties/mysql.properties"></properties><typeAliases><typeAlias type="test.model.Mail" alias="Mail"/><typeAlias type="test.model.Attachment" alias="Attachment"/></typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="UNPOOLED"> <property name="driver" value="${db_driver}" /> <property name="url" value="${db_url}" /> <property name="username" value="${db_user}" /> <property name="password" value="${db_password}"/> </dataSource> </environment> </environments> <mappers><mapper resource="test/data/MailMapper.xml"/><mapper resource="test/data/AttachmentMapper.xml"/> </mappers></configuration> MappersMailMapper.xml
[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  3. <mapper namespace="test.data.MailMapper">  
  4.     <cache />  
  5.   
  6.     <resultMap type="Mail" id="result_base">  
  7.         <id property="id" column="id_mail" />  
  8.         <result property="sender" column="sender"/>  
  9.         <result property="fromAddress" column="from_address" />  
  10.         <result property="subject" column="subject"/>  
  11.         <result property="content" column="content"/>  
  12.         <result property="sendTime" column="send_time" />  
  13.             ....  
  14.     </resultMap>  
  15.     <!--这里是关键,一对多映射的“魔法”几乎都在<collection>的配置里。select=...中"test.data.AttachmentMapper"对应于AttachmentMapper中  
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="test.data.MailMapper"><cache /><resultMap type="Mail" id="result_base"><id property="id" column="id_mail" /><result property="sender" column="sender"/><result property="fromAddress" column="from_address" /><result property="subject" column="subject"/><result property="content" column="content"/><result property="sendTime" column="send_time" /> ....</resultMap><!--这里是关键,一对多映射的“魔法”几乎都在<collection>的配置里。select=...中"test.data.AttachmentMapper"对应于AttachmentMapper中
[html] view plaincopyprint?
  1.             的namespace-->  
  2.     <resultMap type="Mail" id="result" extends="result_base">  
  3.         <collection property="attachments" javaType="ArrayList" column="id_mail" ofType="Attachment"   
  4.         select="test.data.AttachmentMapper.selectByMailId"/>  
  5.     </resultMap>  
  6.       
  7.     <insert id="insert" parameterType="Mail" useGeneratedKeys="true" keyProperty="id_note">  
  8.         insert into note(sender, from_address, subject, content, send_time)  
  9.         values(#{sender}, #{fromAddress}, #{subject}, #{content}, #{sendTime})  
  10.         <selectKey keyProperty="id_mail" resultType="int">   
  11.                       select LAST_INSERT_ID()   
  12.                 </selectKey>   
  13.     </insert>  
  14.       
  15.     <select id="selectById" parameterType="int" resultMap="result" >  
  16.         select * from mail where id_mail = #{id}  
  17.     </select>  
  18.       
  19.     <select id="selectAllMails" resultMap="result">  
  20.         select * from note Note  
  21.     </select>  
  22.     <!--这里可以获得刚插入表格的id,为后面attachment的插入提供了mailId字段-->  
  23.     <select id="selectLastId" resultType="int">  
  24.          select LAST_INSERT_ID()   
  25.     </select>  
  26. </mapper>  
的namespace--><resultMap type="Mail" id="result" extends="result_base"><collection property="attachments" javaType="ArrayList" column="id_mail" ofType="Attachment" select="test.data.AttachmentMapper.selectByMailId"/></resultMap><insert id="insert" parameterType="Mail" useGeneratedKeys="true" keyProperty="id_note">insert into note(sender, from_address, subject, content, send_time)values(#{sender}, #{fromAddress}, #{subject}, #{content}, #{sendTime})<selectKey keyProperty="id_mail" resultType="int"> select LAST_INSERT_ID() </selectKey> </insert><select id="selectById" parameterType="int" resultMap="result" >select * from mail where id_mail = #{id}</select><select id="selectAllMails" resultMap="result">select * from note Note</select><!--这里可以获得刚插入表格的id,为后面attachment的插入提供了mailId字段--><select id="selectLastId" resultType="int"> select LAST_INSERT_ID() </select></mapper> AttachmentMapper.xml
[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  3. <mapper namespace="test.data.AttachmentMapper">  
  4.     <cache />  
  5.       
  6.     <resultMap type="Attachment" id="result">  
  7.         <result property="id" column="id_accessory" />  
  8.         <result property="name" column="name" />  
  9.         <result property="relativePath" column="relative_path" />  
  10.         <result property="mailId" column="id_mail" />  
  11.     </resultMap>  
  12.       
  13.     <insert id="insert" parameterType="Attachment">  
  14.         insert into attachments(id_mail, name, relative_path) values(#{mailId}, #{name}, #{relativePath})  
  15.     </insert>  
  16.     <!--MailMapper中的ResultMap调用这个方法来进行关联-->  
  17.     <select id="selectByMailId" parameterType="int" resultMap="result">  
  18.         select  id, id_mail, name, relative_path  
  19.          from attachments where id_note = #{id}  
  20.     </select>  
  21. </mapper>  
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="test.data.AttachmentMapper"><cache /><resultMap type="Attachment" id="result"><result property="id" column="id_accessory" /><result property="name" column="name" /><result property="relativePath" column="relative_path" /><result property="mailId" column="id_mail" /></resultMap><insert id="insert" parameterType="Attachment">insert into attachments(id_mail, name, relative_path) values(#{mailId}, #{name}, #{relativePath})</insert><!--MailMapper中的ResultMap调用这个方法来进行关联--><select id="selectByMailId" parameterType="int" resultMap="result">select id, id_mail, name, relative_path from attachments where id_note = #{id}</select></mapper>
DAO
AttachmentDAO
[java] view plaincopyprint?
  1. public class AttachmentDAO {  
  2.     private SqlSessionFactory sqlSessionFactory;  
  3.       
  4.     public AttachmentDAO(){  
  5.         this.sqlSessionFactory = TestConnectionFactory.getSqlSessionFactory();  
  6.     }  
  7.       
  8.     public void insert(Attachment attachment){  
  9.              SqlSession session = sqlSessionFactory.openSession();  
  10.              AttachmentMapper attachmentMapper = session.getMapper(AttachmentMapper.class);   
  11.              try {  
  12.                 attachmentMapper.insert(attachment);  
  13.                 session.commit();  
  14.              } finally {  
  15.                 session.close();  
  16.              }  
  17.     }  
  18. }  
public class AttachmentDAO {private SqlSessionFactory sqlSessionFactory;public AttachmentDAO(){this.sqlSessionFactory = TestConnectionFactory.getSqlSessionFactory();}public void insert(Attachment attachment){ SqlSession session = sqlSessionFactory.openSession(); AttachmentMapper attachmentMapper = session.getMapper(AttachmentMapper.class); try { attachmentMapper.insert(attachment); session.commit(); } finally { session.close(); }}}
MailDAO
[java] view plaincopyprint?
  1. public class MailDAO {  
  2.     private SqlSessionFactory sqlSessionFactory;  
public class MailDAO { private SqlSessionFactory sqlSessionFactory;
[java] view plaincopyprint?
  1. public MailDAO(){  
  2.     sqlSessionFactory = TestConnectionFactory.getSqlSessionFactory();  
  3. }   
  4.   
  5. public void insertMailOnly(Mail mail){  
  6.     SqlSession session = sqlSessionFactory.openSession();  
  7.     MailMapper mailMapper = session.getMapper(MailMapper.class);  
  8.     try {  
  9.         mailMapper.insert(mail);         
  10.         session.commit();  
  11.     } finally {  
  12.         session.close();  
  13.     }  
  14. }   
  15. //inset   
  16. public void insertMail(Mail mail){  
  17.     SqlSession session = sqlSessionFactory.openSession();  
  18.     MailMapper mailMapper = session.getMapper(MailMapper.class);  
  19.     AttachmentMapper attachmentMapper = session.getMapper(AttachmentMapper.class);  
  20.       
  21.     try{  
  22.     mailMapper.insert(mail);  
  23.     //这里必须commit,再执行Attachment的插入操作。否则会导致null pointer异常  
  24.     session.commit();  
  25.     //获得最近插入到note表的id  
  26.     int mailId = mailMapper.selectLastId();  
  27.     for(Attachment attach : mail.getAttachments()){  
  28.         attach.setMailId(String.valueOf(mailId));  
  29.         attachmentMapper.insert(attach);  
  30.     }  
  31.     session.commit();  
  32.     }finally{  
  33.         session.close();  
  34.     }  
  35. }  
  36.   
  37. public ArrayList<Mail> selectAllMails(){        
  38.     ArrayList<Mail> mailList = null;  
  39.     SqlSession session = sqlSessionFactory.openSession();  
  40.     MailMapper mailMapper = session.getMapper(MailMapper.class);  
  41.     try {             
  42.         mailList = mailMapper.selectAllMails();  
  43.         session.commit();  
  44.     } finally {  
  45.         session.close();  
  46.     }  
  47. urn mailList;  
  48. }   
  49.   
  50. public Mail selectMailById(int i){  
  51.     Mail mail = null;  
  52.     SqlSession session = sqlSessionFactory.openSession();  
  53.     MailMapper mailMapper = session.getMapper(MailMapper.class);  
  54.     try {             
  55.         mail = mailMapper.selectById(i);  
  56.         session.commit();  
  57.     } finally {  
  58.         session.close();  
  59.     }  
  60. urn mail;  
  61. }  
  62.   
  63. public int selectLastId(){  
  64.     int id = -1;  
  65.     SqlSession session = sqlSessionFactory.openSession();  
  66.     MailMapper mailMapper = session.getMapper(MailMapper.class);  
  67.     try {             
  68.         id = mailMapper.selectLastId();  
  69.         session.commit();  
  70.     } finally {  
  71.         session.close();  
  72.     }  
  73. urn id;  


原创粉丝点击