Java Web --- Mybatis 框架搭建实例

前言

MyBatis是一个优秀的持久层框架。原生的jdbc操作存在大量的重复性代码(如注册驱动,创建连接,创建statement,结果集检测等)。框架的作用就是把这些繁琐的代码封装。

MyBatis通过XML或者注解的方式将要执行的sql语句配置起来,并通过java对象和sql语句映射成最终执行的sql语句。最终由MyBatis框架执行sql,并将结果映射成java对象并返回。

正文

准备jar包

  • mybatis-3.4.6.jar
  • mysql-connector-java-5.1.47.jar 

 mysql数据库为firstdb,表名为xtb,表结构如下

Java Web --- Mybatis 框架搭建实例

 

1.新建java project MybatisPro ,项目结构图:

Java Web --- Mybatis 框架搭建实例

一共五个文件

 

在src下新建com.domain包,在新建User.java

 
  1. package com.domain;

  2.  
  3. public class User {

  4. private Integer user_id;

  5. private String user_name;

  6. private String user_sex;

  7. private String user_phone;

  8.  
  9. public String toString() {

  10. return "User [user_id=" + user_id + ", user_name=" + user_name + ", user_sex=" + user_sex + ", user_phone="

  11. + user_phone + "]";

  12. }

  13.  
  14. public String getUser_phone() {

  15. return user_phone;

  16. }

  17.  
  18. public void setUser_phone(String user_phone) {

  19. this.user_phone = user_phone;

  20. }

  21.  
  22. public String getUser_sex() {

  23. return user_sex;

  24. }

  25.  
  26. public void setUser_sex(String user_sex) {

  27. this.user_sex = user_sex;

  28. }

  29.  
  30. public String getUser_name() {

  31. return user_name;

  32. }

  33.  
  34. public void setUser_name(String user_name) {

  35. this.user_name = user_name;

  36. }

  37.  
  38. public Integer getUser_id() {

  39. return user_id;

  40. }

  41.  
  42. public void setUser_id(Integer user_id) {

  43. this.user_id = user_id;

  44. }

  45. }

 

在src下新建com.Dao包,然后新建Interface文件,UserMapper.java

 
  1. package com.Dao;

  2.  
  3. import com.domain.*;

  4.  
  5. public interface UserMapper {

  6. public User findUserById(int id) throws Exception;

  7.  
  8. public void insertUser(User user) throws Exception;

  9. }

 

在src下新建全局配置文件SqlMapConfig.xml

 
  1. <?xml version="1.0" encoding="UTF-8" ?>

  2. <!DOCTYPE configuration

  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">

  5. <configuration>

  6. <environments default="development">

  7. <environment id="development">

  8. <transactionManager type="JDBC"/>

  9. <dataSource type="POOLED">

  10. <property name="driver" value="com.mysql.jdbc.Driver"/>

  11. <property name="url" value="jdbc:mysql://localhost:3306/firstdb"/><!--用自己的数据库名字 -->

  12. <property name="username" value="root"/> <!-- 用自己的用户名密码 -->

  13. <property name="password" value=""/>

  14. </dataSource>

  15. </environment>

  16. </environments>

  17. <mappers>

  18. <mapper resource="UserMapper.xml"/> <!-- 这里配置映射文件 -->

  19. </mappers>

  20. </configuration>

 

新建映射配置文件UserMpper.xml

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <!DOCTYPE mapper

  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

  5.  
  6. <!-- mapper标签要指定namespace属性,不然会报错,可看做包名-->

  7. <mapper namespace="com.Dao.UserMapper">

  8. <select id="findUserById" parameterType="int" resultType="com.domain.User">

  9. select * from xtb where user_id = #{id}

  10. </select>

  11. <insert id="insertUser" parameterType="com.domain.User">

  12. insert into xtb(user_name,user_sex,user_phone) values(#{user_name},#{user_sex},#{user_phone})

  13. </insert>

  14. </mapper>

 

最后,新建测试类Test.java

 
  1. package com.test;

  2.  
  3. import java.io.InputStream;

  4. import org.apache.ibatis.io.Resources;

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

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

  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;

  8. import com.Dao.UserMapper;

  9. import com.domain.User;

  10.  
  11. public class Test{

  12. public static void main(String[] args) throws Exception {

  13. testInsertUser();

  14. SelectByid();

  15.  
  16. }

  17.  
  18. public static void SelectByid() throws Exception{

  19. String resource = "SqlMapConfig.xml";

  20. InputStream inputStream = Resources.getResourceAsStream(resource);

  21. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

  22. SqlSession session = factory.openSession();

  23. //---------------

  24. UserMapper userMapper = session.getMapper(UserMapper.class);

  25. User user = userMapper.findUserById(2);

  26. System.out.println(user);

  27. //--------------

  28. session.close();

  29.  
  30. }

  31.  
  32. public static void testInsertUser() throws Exception{

  33. String resource = "SqlMapConfig.xml";

  34. InputStream inputStream = Resources.getResourceAsStream(resource);

  35. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

  36. SqlSession session = factory.openSession();

  37. //---------------------

  38. User user = new User();

  39. user.setUser_name("lalala");

  40. user.setUser_sex("women");

  41. user.setUser_phone("0123345");

  42.  
  43. UserMapper mapper = session.getMapper(UserMapper.class);

  44. mapper.insertUser(user);

  45. session.commit();

  46. //----------------------

  47. session.close();

  48. }

  49. }

 

运行程序,查看结果:

Java Web --- Mybatis 框架搭建实例

常见错误解决:

基本上都是UserMapper.xml和接口UserMap.java的对应关系没有配置好,我把UserMapper.xml和UserMap.java拼在一起可以看下自己的配置是否正确:

Java Web --- Mybatis 框架搭建实例

简单来说就是:接口的包名,类名,参数,返回值分别对应着映射文件的namespace,id,parameterType,resultType。

 

总结原理:

mybais运用了代理技术,实例化出接口UserMapper的实例,然后通过根据配置文件调用sql.

具体流程:

1.读取配置文件SqlMapConfig.xml   获取连数据库的相关信息

2.有了这些信息就能创建SqlSessionFactory

3.SqlSessionFactory建立SqlSession

4.SqlSession 通过代理创建出UserMapper接口的实例,并从userMapper.xml中读取信息

5.通过userMapper.xml中的信息,执行sql语句

6.返回结果,关闭session

 

********************************以下为Mybatis使用过程中的注意事项*********************************************

原文连接:https://www.cnblogs.com/pretty-boy/p/5306549.html

使用Mybatis时请注意这两个参数,否则会让你的数据库连接爆掉


     目前正在开发一个产品的服务器端代码,持久层我选择了Mybatis3(也就是原来的ibatis)作为框架,之所以选择他理由就是我觉得Hibernate搞起来貌似很复杂,我不太会用,哈哈(上家公司留下的阴影,用Hibernate搞得我想死)。上周完成了大部分代码的开发工作,想着既然是要发布的产品,于是找来Jmeter做压力测试,结果这一测,暴露问题了,mysql返回"too many connections"这个error,这个error的具体解释参照这个链接http://dev.mysql.com/doc//refman/5.5/en/too-many-connections.html。 
     一般持久层与数据库连接都会通过一个连接池(pooled datasource)管理,方便复用连接,控制并发,比较有名的有DBCP,C3P0,BONECP等等。Mybatis3自己实现了一个连接池,在配置文件中指定datasource的type属性为POOLED即可使用。与并发关系较大的两个Mybatis连接池参数是poolMaximumActiveConnections和poolMaximumIdleConnections。 
      好了,出了问题,自然得找文档(官方手册,中英文皆有),poolMaximumActiveConnections是最大的活动连接数,活动连接,顾名思义,就是正在与数据库交互的连接,默认是10,poolMaximumIdleConnections是空闲连接数,就是没有处理请求的连接,默认是5。Mysql的max_connections我设置的是200,既最大连接数。这样一看,好像找不到问题所在,连接池最大的活动连接也就是10,跟200比还差很远,Mysql怎么会返回"too many connections"呢?在查阅文档无果后,我请教周围的一位同事,他虽然没用过Mybatis,但是他说是不是请求数超过poolMaximumActiveConnections后mybatis还会去获取连接,是不是有这样的参数控制,然后让我看看源码,说开源的东西嘛,搞不清楚就看源码。 
      我一向对源码抱有恐惧的心理,感觉那都是大神写的,我等屌丝怎能看得懂,不过被逼无奈,翻出Mybatis的源码看了一看,结果豁然开朗。找到org.apache.ibatis.datasource.pooled包下面的PooledDataSource类,这个就是连接池的实现类。可以看到里面定义了几个参数,其中就包括poolMaximumActiveConnections和poolMaximumIdleConnections,找到pushConnection方法,这个方法里会判断当前空闲连接数和poolMaximumIdleConnections的大小,如果小于他,会new PooledConnection并放进队列中,这就导致一个问题,当所有的连接被占满后,Mybatis为了保持一定的空闲连接,会不断获取新的连接,然后这些新连接被占用后,就会再去new PooledConnection,结果就是超过了mysql设置的最大连接数,然后数据库返回该错误。不知道这算不算是Mybatis的一个"坑"吧,总之在使用时要小心了,并发量大的时候就会爆掉你的数据库,解决办法很简单,将poolMaximumIdleConnections设置为0即可,果然改掉后压力测试不会爆掉数据库。 
       现在回想起来,官方文档对poolMaximumIdleConnections的定义是:在任意时间存在的空闲连接数,完全就解释了这个参数的含义,只不过当时没有仔细想,那这个参数是不是该改名字叫poolPermanentIdleConnections比较好呢,呵呵。 
问题解决了,很开心,晚上回去再仔细读下里面的源码,看看还有没有别的没发现的问题。看来源码也不是想象中的那么神秘和高深啊。其实为什么那个同事一下就能看出问题的大概,一方面是经验丰富,另一方面可能与他理解数据库连接池机制有关,归根到底,基础的东西还是最重要的。

        回去认真读了Mybatis源码,发现自己错了,特此更正,以免误导读者,实在是对不起。其实poolMaximumActiveConnections的存在可以正确地限制数据库连接池并发访问数据的连接数,没有问题,之所以我的数据库爆掉了,是我没有正确地维持SqlSessionFactory这个类的一个单例。在使用时一定要保持一个全局唯一的SqlSessionFactory