• Mybatis


    一、介绍

    Mybatis就是类似于Hibernate的ORM(对象关系映射:把对象模型表示的对象映射到基于SQL的关系模型数据库结构中,在具体的操作实体对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作实体对象的属性和方法)持久层框架。Mybatis封装了jdbc访问数据库的过程,开发时只需专注于SQL语句本身的拼装,其它复杂的过程全部可以交给Mybatis去完成。

    二、Jdbc访问数据库的过程:

    	public static void main(String[] args) {
    	
    	      Connection connection = null;
    	      PreparedStatement preparedStatement = null;
    	      ResultSet resultSet = null;
    	      try {
    	      //加载数据库驱动
    	      Class.forName("com.mysql.jdbc.Driver");
    	      //根据驱动管理类获取连接
    	      connection =
    	      DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","root","root");
    	      //定义sql语句   ?表示占位符
    	      String sql = "select * from user where username = ?";
    	      //获取预处理 statement
    	      preparedStatement = connection.prepareStatement(sql);
    	      //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
    	      preparedStatement. setString(1, "王五");
    	      //向数据库发出sql执行查询,查询出结果集
    	      resultSet = preparedStatement.executeQuery();
    	      //遍历查询结果集
    	      while (resultSet.next()) {
    	    	  System.out.println(resultSet. getString("id") +" "+resultSet.getString( "username"));
                    }
    	      } catch (Exception e) {
    	    	  e.printStackTrace();
    	      } 
    	      finally {
    	    	  //释放资源
    		      if (resultSet != nu1l) {
    		    	  try {
    		    		  resultSet.close();
    
    		    	  } catch (SQLException e) {
    		    		  	e. printStackTrace();
    		    	  }
    		      }
    		      if (preparedStatement != null) {
    
    		    	  try {
    		    		  preparedStatement . close();
    		    	  }catch (SQLException e){
    		    		  e. printStackTrace();
    		    		  }
    		      }
    		      if (connection != null){
    		    	  try {
    		    		  connection.close();
    		    	  }catch (SQLException e) {
    		    		  e.printStackTrace();
    		    	  }
    		      }
    	      }
    	      }
    
    

    三、Jdbc存在的问题:

    1、数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。
    解决:sqlMapConfig.xml中配置连接池,使用连接池管理数据库连接。
    2、Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql 变动需要改变java代码。
    解决:将sql配置在XXmapper.xml中,实现sql与java代码分离。
    3、使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,占位符需要一一对应。
    解决:mybatis自动将java对象映射到sql语句,通过statement的parameterType定义输入类型。
    4、对结果集解析存在硬编码( 查询列名),sql 变化导致解析代码变化,系统不易维护,如能将数据库记录封装成pojo对象解析较方便。
    解决:mybatis自动将jsql执行结果映射到java对象,通过statement的resultType定义输出结果类型。

    四、Mybatis架构

    五、mybatis与hibernate的区别

    Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自已编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java 对象。
    Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
    Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
    总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。

    六、使用Mybatis开发DAO

    1、传统Dao开发方式

    大致步骤:

    1、pojo----->user.java
    2、Dao--->UserDao.java(接口)
    3、mapper.xml--->user.xml

    <mapper namespace="test">
    <!-- id:statementId
    		 resultType:查询结果集的数据类型
    		 parameterType:查询的入参
    	-->
    	<select id="getUserById" parameterType="int" resultType="com.baidu.mybatis.pojo.User" >
    		SELECT * FROM USER WHERE id = #{id1}
    	</select>
    	<select id="getUserByName" parameterType="string" resultType="com.baidu.mybatis.pojo.User" >
    		SELECT * FROM USER WHERE username LIKE #{username }    //  '%${value}%'
    	</select>
    
    </mapper>
    

    #{} 表示一个占位符号,通过#{}可实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可有效防止sql注入。#{}可接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
    ${} 表示拼接sql串,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
    4、SqlMapConfig.xml

    <configuration>
        <mappers>
            <mapper resource="sqlMap/user.xml"/>
        </mappers>
    </configuration>
    

    5、DaoImpl--->UserDaoImpl.java

    @Test
    	public void testGetUserByid() throws IOException {
    		// 创建SqlSessionFactoryBuilder对象
    		SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
    		// 查找配置文件创建输入流
    		InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    		// 加载配置文件,创建SqlSessionFactory对象
    		SqlSessionFactory	sqlSessionFactory = sfb.build(inputStream);
    		// 创建SqlSession对象
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		// 执行查询,参数一:要查询的statementId ,参数二:sql语句入参
    		User user = sqlSession.selectOne("user.getUserById", 1);
                    List<User> list= sqlSession.selectList("user.getUserByName","%王%"); //#{username }
                    List<User> list= sqlSession.selectList("user.getUserByName","王");//%${username }%
    
    		// 输出查询结果
    		System.out.println(user);
    		// 释放资源
    		sqlSession.close();
    	}
    
    

    2、动态代理开发Dao

    Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
    Mapper接口开发需要遵循以下规范:
    1、Mapper.xml 文件中的namespace与mapper接口的类路径相同。
    2、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
    3、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的arameterType的类型相同
    4、Mapper 接口方法的输出参数类型和mapper.xml 中定义的每个sql 的 resultType的类型相同

    大致步骤:

    1、pojo----->user.java
    2、Mapper.java(接口文件)-->UserMapper.java

    public interface UserMapper{
    	
    	user getUserById(int id);
    
    }
    

    3、mapper.xml--->UserMapper.xml

    <mapper namespace="com.baidu.mapper.UserMapper">
    
    	<select id="getUserById" parameterType="int" resultType="com.baidu.mybatis.pojo.user" >
    		SELECT * FROM USER WHERE id = #{id1}
    	</select>
    
    </mapper>
    

    4、SqlMapConfig.xml

    <configuration>
        <mappers>
            <mapper resource="mapper/UserMapper.xml"/>
            <!--包扫描,需要mapper,xml与mapper接口名称相同-->
            <mapper package="com.baidu.mapperl"/>
        </mappers>
    </configuration>
    

    测试

    	public void testGetUserByid() throws IOException {
    		// 创建SqlSessionFactoryBuilder对象
    		SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
    		// 查找配置文件创建输入流
    		InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    		// 加载配置文件,创建SqlSessionFactory对象
    		SqlSessionFactory	sqlSessionFactory = sfb.build(inputStream);
    		// 创建SqlSession对象
    		SqlSession sqlSession = sqlSessionFactory.openSession();
            //从sqlSession中获取Mapper接口的代理对象
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    		//执行查询方法
            User user = userMapper.queryUserById(1);
    		System.out.println(user);
            //和spring整合后由spring管理
    		sqlSession. close();}
    
    	
    	}
    
    

    七、类型别名typeAliases

    在sqlMapConfig中配置

    <typeAliases>
    	<!--单个别名定义 -->
    	<typeAlias alias="user" type="com.baidu.pojo.user"/>
    	<!--批量别名定义,扫描整个包下的类,别名为类名(大小写不敏感) -->
    	<package name="com.baidu.pojo"/>
    	<package name="其他包"/>
    </typeAliases>
    

    mapper.xml中

    	<select id="getUserById" parameterType="int" resultType="uSeR" >//大小写不敏感
    		SELECT * FROM USER WHERE id = #{id}
    	</select>
    

    八、resultMap

    resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
    如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系,resultMap 实质上还需要将查询结果映射到pojo 对象中。
    resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

    <mapper namespace= "com.baidu.mapper.OrderMapper">
    
    <!--resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪个pojo -->
    <!-- id: 设置ResultMap的id -->
    <resultMap type="order" id="orderResultMap">
    <!--定义主键,非常重要。如果是多个字段,则定义多个id -->
    <!-- property: 主键在pojo中的属性名-->
    <!-- column: 主键在数据库中的列名-->
    <id  property="id" column="id">
    <!--定义普通属性-->
    <result property="userId" column= "user_id"/>
    <result property= "number" column= "number"/>
    <result property= "createt ime" column= "createtime"/>
    <result property ="note" columne "note"/>
    
    <!-- 查询所有订单数据 -->
    
    	<select id= "query0rderALl" resultMap= "orderResultMap" >
    
    	SELECT id, user_ id,number,
    	createtime, note FROM 'order'
    	</select>
    
    </mapper>
    

    九、动态sql

    1、<if></if>
    	<select id= "getIdByWhere parameterType="user" resultType="user"  >
    	SELECT id FROM 'user' 
    	where 1=1
    		<if test="sex!=null and sex!=" "">
    			And sex=#{sex}
    		</if>
    		<if test="username!=null and username!=" "">
    			And username=#{username}
    		</if>
    	</select>
    
    2、<where></where>
    
    	<select id= "getIdByWhere parameterType="user" resultType="id"  >
    		SELECT id FROM 'user' 
    		<where>
    			<if test="sex!=null and sex!=" "">
    				And sex=#{sex}
    			</if>
    			<if test="username!=null and username!=" "">
    				And username=#{username}
    			</if>
    		</where	>
    	</select>
    
    3、<sql></sql>
    
    	<select id= "getUserByWhere parameterType="user" resultType="user"  >
    		SELECT <include refid="userFields"/> FROM 'user' 
    		<where>
    			<if test="sex!=null and sex!=" "">
    				And sex=#{sex}
    			</if>
    			<if test="username!=null and username!=" "">
    				And username=#{username}
    			</if>
    		</where	>
    	</select>
    	<sql id="userFields">
    		id,username,sex
    	</sql>
    
    4、<foreace></foreach>
    <select id= "queryUserByIds" parameterType= "queryVo" resultType= "user">
          SELECT * FROM、user
    	  <where>
          <!-- foreach标签,进行遍历-->
          <!-- collection: 遍历的集合,这里是QueryVo的ids属性-->
          <!-- item: 遍历的项目,可以随便写,,但是和后面的#{}里面要一致-->
    	  <!-- open: 在前面添加的sql片段-->
    	  <!-- close: 在结尾处添加的sq1片段-->
          <!-- separator:指定遍历的元素之间使用的分隔符-->
    		<foreach collection= "ids" item= "item" open="id IN (" close=")"
    		separator=",">
    		#{item}
    		</foreach>
    	  </where>
    </select>
    

    十、关联查询

    十一、Mybatis逆向工程

    十二、Mybatis整合Spring

    整合思路
    1、SqISessionFactory 对象应该放到spring容器中作为单例存在。
    2、传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
    3、Mapper 代理形式中,应该从spring容器中直接获得mapper的代理对象。
    4、数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

  • 相关阅读:
    php二维数组排序
    重学C语言 -- printf,scanf
    php调试利器 -- xdebug
    composer php依赖管理工具
    现代php开发
    php新特性--持续更新
    2016年书单
    jenkins集成gitlab实现自动合并
    etcd安装
    nginx 日志切割
  • 原文地址:https://www.cnblogs.com/StephenChenin/p/9770724.html
Copyright © 2020-2023  润新知