mybatis 笔记

mybatis在数据量大的情况下,还是比较推荐使用的,因为有利于sql的性能优化。下面将讲讲我对mybatis的理解。

   每 一 个 MyBatis 的 应 用 程 序 都 以 一 个 SqlSessionFactory 对 象 的 实 例 为 核 心 。SqlSessionFactory本身是由SqlSessionFactoryBuilder创建的,一般而言,在一个应用中,一个数据库只会对应一 个SqlSessionFactory,所以一般我们都把SqlSessionFactory定义成单例模式,或通过Spring等进行注入

  例如:下面我就用单例模式,来创建了一个SqlSessionFactory,用于junit test的使用。

  

 1 public class SqlHelper {
 2     private static  SqlSessionFactory S_FACTORY = null;
 3     private static SqlSession session = null;
 4     public static SqlSessionFactory initFactory() {
 5         if (S_FACTORY == null) {
 6             String resource = "configs.xml";
 7             try {
 8                 InputStream inputStream = Resources.getResourceAsStream(resource);
 9                 S_FACTORY = new SqlSessionFactoryBuilder().build(inputStream);
10             } catch (IOException e) {
11                 // TODO Auto-generated catch block
12                 e.printStackTrace();
13             }
14             
15         }
16         return S_FACTORY;
17     }
18     @Test
19     public void getSqlFactory() {
20         initFactory();
21     }
22     public static SqlSession getSqlSession() {  
23         if (S_FACTORY == null) {
24             initFactory();
25         } 
26         if (session == null) {
27             session = S_FACTORY.openSession();           
28         }
29         return session;
30     }
31     public static  void closeSession() {
32         if (session != null) {
33             session.close();
34             session = null;
35         }
36     }
37 }
View Code

   接下来就是编写映射文件,pojo类,以及在mybatis配置文件中对使用到的mapper.xml进行注册,和数据库的链接。

   但是笔者感觉编写映射文件,pojo类工作量有点大,所以笔者想到通过用代码的方式通过数据库的表反向映射这些东西,减少工作量。

   first:编写一个配置文件

  

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
 
  <!-- 配置mysql 驱动jar包路径.用了绝对路径 -->
  <classPathEntry location="C:\Users\Tom\.m2\repository\mysql\mysql-connector-java\5.1.10\mysql-connector-java-5.1.10.jar" />

  <context id="tom_mysql_tables" targetRuntime="MyBatis3">
 
    
    <commentGenerator>
      <property name="suppressAllComments" value="true" />
      <property name="suppressDate" value="true" />
    </commentGenerator>
    <!-- 注释控制完毕 -->
 
    <!-- 数据库连接 -->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver"
        connectionURL="jdbc:mysql://127.0.0.1:3306/logistics?useUnicode=true&amp;characterEncoding=UTF-8"
        userId="root"
        password="root">
    </jdbcConnection>

    <javaTypeResolver >
      <property name="forceBigDecimals" value="false" />
    </javaTypeResolver>
   
    <!-- 数据表对应的model 层  -->
    <javaModelGenerator targetPackage="com.tom.model" targetProject="src/main/java">
      <property name="enableSubPackages" value="true" />
      <property name="trimStrings" value="true" />
    </javaModelGenerator>
   
    <!-- sql mapper 隐射配置文件 -->
    <sqlMapGenerator targetPackage="com.tom.mapper"  targetProject="src/main/java">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
   
    <!-- 在ibatis2 中是dao层,但在mybatis3中,其实就是mapper接口 -->
    <javaClientGenerator type="XMLMAPPER" targetPackage="com.tom.inter"  targetProject="src/main/java">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
   
    <!-- 要对那些数据表进行生成操作,必须要有一个. -->
    <table schema="logistics" tableName="account" domainObjectName="Account"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">    
    </table>
    <table schema="logistics" tableName="address" domainObjectName="Address"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">    
    </table>
     <table schema="logistics" tableName="admin" domainObjectName="Admin"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">    
    </table>
     <table schema="logistics" tableName="line" domainObjectName="Line"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">    
    </table>
     <table schema="logistics" tableName="orders" domainObjectName="Orders"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">    
    </table>
    <table schema="logistics" tableName="storage" domainObjectName="Storage"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">    
    </table>
  </context>
</generatorConfiguration>
View Code

 

 second:编写类

 1 package com.tom.test;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.sql.SQLException;
 6 import java.util.ArrayList;
 7 import java.util.List;
 8 
 9 import org.mybatis.generator.api.MyBatisGenerator;
10 import org.mybatis.generator.config.Configuration;
11 import org.mybatis.generator.config.xml.ConfigurationParser;
12 import org.mybatis.generator.exception.InvalidConfigurationException;
13 import org.mybatis.generator.exception.XMLParserException;
14 import org.mybatis.generator.internal.DefaultShellCallback;
15 
16 public class GenMain {
17     public static void main(String[] args) {
18         List<String> warnings = new ArrayList<String>();
19         boolean overwrite = true;
20         String genCfg = "/generatorConfig.xml";
21         File configFile = new File(GenMain.class.getResource(genCfg).getFile());
22         ConfigurationParser cp = new ConfigurationParser(warnings);
23         Configuration config = null;
24         try {
25             config = cp.parseConfiguration(configFile);
26         } catch (IOException e) {
27             e.printStackTrace();
28         } catch (XMLParserException e) {
29             e.printStackTrace();
30         }
31         DefaultShellCallback callback = new DefaultShellCallback(overwrite);
32         MyBatisGenerator myBatisGenerator = null;
33         try {
34             myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
35         } catch (InvalidConfigurationException e) {
36             e.printStackTrace();
37         }
38         try {
39             myBatisGenerator.generate(null);
40         } catch (SQLException e) {
41             e.printStackTrace();
42         } catch (IOException e) {
43             e.printStackTrace();
44         } catch (InterruptedException e) {
45             e.printStackTrace();
46         }
47     }
48 }
View Code

 运行main方法,very good,mapper.xml与javabean都已经生成,省了好多事。

 接下来你可以具体的mapper.xml提交你要添加的sql.

  对于select ,update ,insert,delete标签中都有一些参数,常用的如:parameterType ,resultMap, resultType,parameterMap.

  如parameterMap的使用,直接上代码。

 

<!-- 调用存储过程 -->
  <select id="getUserCount" parameterMap="paramMaps" statementType="CALLABLE">
      CALL logistics.get_user_count(?,?)
  </select>
  <parameterMap type="java.util.Map" id="paramMaps">
    <parameter property="sexId" mode="IN" jdbcType="INTEGER"/>
    <parameter property="sexcount" mode="OUT" jdbcType="INTEGER"/>
  </parameterMap>
View Code
package com.tom.junt;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.tom.VO.VOUser;
import com.tom.bean.Classes;
import com.tom.bean.User;
import com.tom.mapper.ClassesMapper;

public class ClassMapperTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        SqlSessionFactory factory =    SqlHelper.initFactory();
        //Classes classes = factory.openSession().getMapper(ClassesMapper.class).getClassInfo(1);
        //Classes classes = factory.openSession().selectOne("com.tom.mapper.ClassesMapper.getClassInfo2", 1);        
        //Classes classes = factory.openSession().selectOne("com.tom.mapper.ClassesMapper2.getClassInfo", 1);
        //Classes classes = factory.openSession().selectOne("com.tom.mapper.ClassesMapper2.getClassInfo2", 1);
        SqlSession session = factory.openSession();
        //List<User> users = session.selectList("com.tom.mapper.UserMapper.getUserInfo",new VOUser("州", 19,26));
        Map<String,Integer> parameterMap = new HashMap<String, Integer>();
        parameterMap.put("sexId",1);
        parameterMap.put("sexcount",-1);
        session.selectOne("com.tom.mapper.UserMapper.getUserCount", parameterMap);
        System.out.println(parameterMap.get("sexcount"));
        session.close();
    }

}
View Code

  at last:

    介绍一下,常用的两种查询方式(嵌套结果,嵌套查询):注意assocation and collection标签的使用。

    嵌套结果:(classes与teacher一对一,classes与student一对多)

   

<sql id="classInfo">
      c.c_id,c.name,t.t_id,t.t_name,s.s_id,s.s_name
  </sql>
<!-- 嵌套结果 (就是通过联表查询,去除重复部分)-->
  <resultMap type="classes" id="classInfoMap">
     <id property="id" column="c_id"/>
     <result property="name" column="name"/>
     <association property="teacher" javaType="teacher">
       <id property="id" column="t_id"/>
       <result property="name" column="t_name"/>
     </association>
     <collection property="students" ofType="student">
        <id property="id" column="s_id"/>
        <result property="name" column="s_name"/>
     </collection>
  </resultMap>
<select id="getClassInfo" parameterType="int" resultMap="classInfoMap">
      select
      <include refid="classInfo"></include>
      from classes as c,teacher as t,student s
      where
      t.t_id=c.teacher_id
      and c.c_id=s.class_id
      and c.c_id=#{id}
  </select>
View Code

 

  嵌套查询:

 

<sql id="classInfo2">
    c.c_id,c.name,c.teacher_id
  </sql>
<resultMap type="classes" id="classInfoMap2">
   <id property="id" column="c_id"/>
   <result property="name" column="name"/>
   <association property="teacher" column="teacher_id" select="getTeacherInfo">
   </association>
   <collection property="students" column="c_id" select="getStudentInfo"></collection>
  </resultMap>
<!-- 嵌套查询 -->
  <select id="getClassInfo2" parameterType="int" resultMap="classInfoMap2">
    select
    <include refid="classInfo2"></include>
    from classes c
    where c.c_id=#{id}
  </select>
  <select id="getTeacherInfo" parameterType="int" resultType="teacher">
     select t.t_id as id,t.t_name as name from teacher t where t.t_id=#{id}
  </select>
  <select id="getStudentInfo" parameterType="int" resultType="student">
    select s_id id,s_name name from student where class_id=#{id}
  </select>
View Code

使用mybatis的常见问题:

1:在mybatis的使用中,会碰到有些特殊字符被xml解析器不必要的解析了,结果就报错了。

解决方案:

<![CDATA[sql语句]]>,其中包裹的sql语句就会被xml解析器忽略。

2:

出现error:

the JdbcType must be specified for all nullable parameters. Cause: java.sql.SQLException: 无效的列类型: 1111 ; uncategorized SQLException for SQL []; SQL state [99999]; error code [17004]; 无效的列类型: 1111; nested exception is java.sql.SQLException: 无效的列类型: 1111.

原因:

在持久化到数据库的时候,你的参数中存在null,mybatis根据参数得到当前参数得类型,如果是null,默认就是jdbcType.Other类型,所以就报错了。

解决方案:

对于可能会是null的参数加上jdbcType=’’,例如:

insert into account (id, username, password,

      email, usercode, engcode,

      name, sex, cardid,

      phone, address, qq,

      admin_id)

    values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},

      #{email,jdbcType=VARCHAR}, #{usercode,jdbcType=VARCHAR}, #{engcode,jdbcType=VARCHAR},

      #{name,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR}, #{cardid,jdbcType=VARCHAR},

      #{phone,jdbcType=VARCHAR}, #{address,jdbcType=VARCHAR}, #{qq,jdbcType=INTEGER},

      #{adminId,jdbcType=INTEGER})

 

 

    学习资料:

    

http://www.cnblogs.com/rollenholt/p/3365866.html

 

 

 

http://blog.csdn.net/killer_zr/article/details/7652951

 

posted @ 2016-03-06 23:44  Tom_Plus  阅读(137)  评论(0)    收藏  举报