zoukankan      html  css  js  c++  java
  • Mybatis框架学习01

    写在前面

    在查找了各路学习的课程后,选择了学习SSM,即Spring+SpringMVC+Mybatis。今天主要学习了Mybatis的基础知识。

    1.传统JDBC的问题

    先来看一段JDBC的经典代码:

    public static void main(String[] args) {
    		//数据库连接
    		Connection connection = null;
    		//预编译的Statement,使用预编译的Statement
    		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", "abc456");
    			//定义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!=null){
    				try {
    					resultSet.close();
    				} catch (SQLException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    			if(preparedStatement!=null){
    				try {
    					preparedStatement.close();
    				} catch (SQLException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    			if(connection!=null){
    				try {
    					connection.close();
    				} catch (SQLException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    
    		}
    
    	}
    

    从这段代码中,我们可以读到几个问题:

    • 1.数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响 数据库性能。
    • 2.将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。
    • 3.向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
    • 4.从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,,不利于系统维护。

    可以看到,传统的JDBC有很多的问题,我们设想一下如何来解决:

    • 1.使用数据库连接池来管理连接。
    • 2&&3&&4:放到xml配置文件中,形成软编码。

    在大致了解后,正式进入Mybatis的学习

    2.Mybatis的运行原理:

    我们首先看一张图:

    这张图细致的描述了Mybatis的运行原理:Mybatis首先通过一个总配置文件(SqlMapConfig.xml,名称不固定),来配置各种映射文件和事务等。之后建立一个会话工厂,通过总配置文件会话工厂,会话工厂创建一个面向用户的接口,来实现操作数据库,其实际上是通过Executor来控制数据库,而Executor则是使用mapped statement来对数据库进行直接操作。这就是Mybatis的运行原理。

    3.Mybatis的测试程序

    3.1 按照上面的流程,我们首先要写一个总配置文件SqlMapConfig.xml:

    <?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>
    	<!-- 和spring整合后 environments配置将废除-->
    	<environments default="development">
    		<environment id="development">
    		<!-- 使用jdbc事务管理,事务控制由mybatis控制-->
    			<transactionManager type="JDBC" />
    		<!-- 数据库连接池,由mybatis管理-->
    			<dataSource type="POOLED">
    				<property name="driver" value="com.mysql.jdbc.Driver" />
    				<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
    				<property name="username" value="root" />
    				<property name="password" value="abc456" />
    			</dataSource>
    		</environment>
    	</environments>
    	<!-- 加载映射文件 -->
    	<mappers>
    		<mapper resource ="sqlmap/User.xml"></mapper>
    	</mappers>
    </configuration>
    

    其中定义了mappers,即第二步的映射对象。

    3.2映射对象的配置(User.xml):

    <?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">
    <!-- namespace 命名空间,作用就是对sql进行分类化管理,理解sql隔离 注意:使用mapper代理方法开发,namespace有特殊重要作用 -->
    <mapper namespace="test">
    	<!-- 在映射文件中配置很多sql语句 -->
    	<!-- 通过select进行数据库的查询,按id查询user表 id:标识映射文件中的sql,称为statement的id 将sql语句封装到mapperStatement对象中,所以将id称为statement的id -->
    	<!-- #{}表示一个占位符号 -->
    	<!-- parameterType 指定输入参数的类型,这里指定int型 -->
    	<!-- #{id}:其中的id表示接收输入的参数,参数的名称就是id 如果输入参数是简单类型,#{}中的参数名可以任意 -->
    	<!--resultType:指定sql输出结果所映射的java对象类型:select指定resultType 表示将单条记录映射成java对象 -->
    	<select id="findUserById" parameterType="int"
    		resultType="mybatis01.po.User">
    		select * from user where id =#{id}
    	</select>
    	<!-- 根据用户名称模糊查询用户信息 可能返回多条 resultType:指定的就是单条记录所映射的java对象类型 -->
    	<!-- ${}:表示拼接sql串,将接收到的内容不加任何修饰拼接在sql中
    	使用${}拼接sql可能会引起sql注入
    	${value}:接收输入参数的内容,如果传入类型是简单类型,${}中只能使用value
    	 -->
    	<select id="findUserByName" parameterType="java.lang.String"
    		resultType="mybatis01.po.User">
    		select * from user where username like '%${value}%'
    	</select>
            <insert id="insertUser" parameterType="mybatis01.po.User">
    		<!-- 
    		将插入数据的主键返回,返回到USER对象中
    		select last_insert_id():得到insert进去记录的主键值,只适用于自增主键
    		
    		keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
    		order:select last_insert_id()执行顺序(相对于insert语句来说)
    		
    		resultType:指定select last_insert_id()的结果类型
    		 -->
    		<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
    			SELECT LAST_INSERT_ID()
    		</selectKey>
    		
    		insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
    	</insert>
    	
    	<!-- 删除用户 
    	根据id删除用户,需要输入id值
    	-->
    	<delete id="deleteUser" parameterType="java.lang.Integer">
    		delete from user where id = #{id}
    	</delete>
    	
    	<!-- 更新用户
    	需要传入用户id
    	需要传入用户的更新信息
    	parameterType指定user对象,包括id和更新信息,注意,id必须存在
    	 #{id} 从输入的user对象中获取id属性值
    	 -->
    	
    	<update id="updateUser" parameterType="mybatis01.po.User">
    		update user set username = #{username},birthday=#{birthday},sex=${sex},address=#{address} where id = #{id}
    	</update>
    </mapper>
    

    这里编写主要的sql语句以及接受和发出的各种参数,具体的操作解释都在注释里。
    其中由于操作的是User对象,我们要创建一个User对象:

    public class User {
    
    	//属性名和数据库表的字段对应
    	private int id;
    	private String username;// 用户姓名
    	private String sex;// 性别
    	private Date birthday;// 生日
    	private String address;// 地址
    	
    }
    
    

    3.3 在配置完成后,我们写一个测试程序来测试Mybatis,这里在User.xml定义了两个sql语句,分别是按ID查找和按名称模糊查找,我们分别编写方法:

    	//根据id查询用户信息,得到一条记录的结果
    	@Test
    	public void findUserByIdTest() throws IOException {
    		//mybatis配置文件
    		String resource = "SqlMapConfig.xml";
    		//得到配置文件流
    		InputStream config = Resources.getResourceAsStream(resource);
    		//创建会话工厂
    			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    		//通过工厂得到SqlSession
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		//通过SqlSession操作数据库
    		//第一个参数,映射文件中statement的 id=namespace+"."+statment的id
    		//第二个参数:指定映射文件中所匹配的parameterType类型的参数
    		//selectone的结果是与映射文件中所匹配的resultType类型的对象
    		User  user = sqlSession.selectOne("test.findUserById",1);
    		System.out.println(user);
    		//释放资源
    		sqlSession.close();
    	}
    	
    	//根据用户名称模糊查询用户列表
    	
    	@Test
    	public void findUserByNameTest() throws IOException {
    		//mybatis配置文件
    				String resource = "SqlMapConfig.xml";
    				//得到配置文件流
    				InputStream config = Resources.getResourceAsStream(resource);
    				//创建会话工厂
    					SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    				//通过工厂得到SqlSession
    				SqlSession sqlSession = sqlSessionFactory.openSession();
    				//list中的user和映射文件中resultType所指定的类型一致
    				List<User> list = sqlSession.selectList("test.findUserByName","小明");
    				System.out.println(list);
    				sqlSession.close();
    	}
            //添加用户
    	@Test
    	public void insertNameTest() throws IOException {
    				//mybatis配置文件
    				String resource = "SqlMapConfig.xml";
    				//得到配置文件流
    				InputStream config = Resources.getResourceAsStream(resource);
    				//创建会话工厂
    					SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    				//通过工厂得到SqlSession
    				SqlSession sqlSession = sqlSessionFactory.openSession();
    				//插入用户对象
    				User user = new User();
    				user.setUsername("赵淫荡");
    				user.setBirthday(new Date());
    				user.setSex("1");
    				user.setAddress("武安市第一中学");
    				sqlSession.insert("test.insertUser",user);
    				//执行提交事务
    				sqlSession.commit();
    				//获取用户信息主键
    				System.out.println(user.getId());
    				//关闭会话
    				sqlSession.close();
    	}
    	//删除用户
    	@Test
    	public void deleteUserTest() throws IOException {
    				//mybatis配置文件
    				String resource = "SqlMapConfig.xml";
    				//得到配置文件流
    				InputStream config = Resources.getResourceAsStream(resource);
    				//创建会话工厂
    					SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    				//通过工厂得到SqlSession
    				SqlSession sqlSession = sqlSessionFactory.openSession();
    				//传入id,删除用户
    				sqlSession.delete("test.deleteUser",39);
    				//执行提交事务
    				sqlSession.commit();
    				//获取用户信息主键
    				//关闭会话
    				sqlSession.close();
    	}
    	//更新用户
    	@Test
    	public void updateUserTest() throws IOException {
    				//mybatis配置文件
    				String resource = "SqlMapConfig.xml";
    				//得到配置文件流
    				InputStream config = Resources.getResourceAsStream(resource);
    				//创建会话工厂
    					SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    				//通过工厂得到SqlSession
    				SqlSession sqlSession = sqlSessionFactory.openSession();
    				User user = new User();
    				user.setId(37);
    				user.setUsername("赵荡荡");
    				user.setBirthday(new Date());
    				user.setSex("1");
    				user.setAddress("武安市第中学");
    				//传入id,删除用户
    				sqlSession.update("test.updateUser",user);
    				//执行提交事务
    				sqlSession.commit();
    				//获取用户信息主键
    				//关闭会话
    				sqlSession.close();
    	}
    

    并通过JUnit进行测试,测试无误。

  • 相关阅读:
    python学习第四天 --字符编码 与格式化及其字符串切片
    Lambda表达式 之 C#
    python学习第三天 --布尔类型
    深入理解正则表达式
    《你不知道的JavaScript》第一部分:作用域和闭包
    jquery的extend和fn.extend
    HttpModule与HttpHandler详解
    jQuery分析(2)
    jQuery分析(1)
    jQuery源码中的“new jQuery.fn.init()”什么意思?
  • 原文地址:https://www.cnblogs.com/wushenjiang/p/12451977.html
Copyright © 2011-2022 走看看