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 }
接下来就是编写映射文件,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&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>
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 }
运行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>
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(); } }
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>
嵌套查询:
<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>
使用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
浙公网安备 33010602011771号