框架学习一:使用Mybatis的原因和优点

jdbc 与 Mybatis的比较

一、原生态jdbc的不足:

1.数据库连接,使用时创建,不使用时立即释放,造成对数据库频繁的连接开启和关闭,造成数据库资源的浪费,影响数据库性能。
解:使用数据库连接池管理数据库连接。
2.将SQL语句硬编译到Java程序代码中,若修改SQL语句,则需要重新编译Java代码,不利于系统维护。
设想:将SQL语句设置到xml配置中,若SQL改变,不需要重新编译Java代码。
3.向PreparedStatement中设置参数,对占位符和设置参数值硬编译在Java代码中,SQL语句修改,则需要重新编译java代码,不利于系统维护。
设想:将SQL语句和占位符、参数全部配置在xml文件中,当修改SQL时,不需要再重新编译Java代码。
4.从resultSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护。
设想:将查询的结果集,自动映射成Java对象。

中级:Servlet + JSP + JavaBean – 实现小型项目使用jdbc即可满足需求。
框架:适合中型/大型项目 – 稳定,利于扩展,利于维护,适合更多人同时访问(高并发)

二、Mybatis框架

**1.什么是Mybatis:Mybatis是一个持久型框架:可以连接操作数据库的**

	(1)mybatis是一个持久框架层,是Apache下的顶级项目,最后托管到了GitHub([https://github.com/mybatis/mybatis-3/releases])
	(2)mybatis让程序将主要放在SQL上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写SQL)满足需要的SQL语句。
	(3)mybatis可以将preparedStatement中的输入参数自动进行输入映射,将查询的结果集映射成Java对象(输出映射)。
	参数-->SQL:输入映射  	  SQL-->java:输出映射

**2.mybatis框架工作原理**

	(1)mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的信息。 
	(2)mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
	(3)通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。 
	(4)SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
	(5)Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括java的简单类型、HashMap集合对象、POJO对象类型。

三、程序应用实现

1.项目要求:
	(1)根据用户id(主键)查询用户信息
	(2)根据用户名称模糊查询用户信息
	(3)添加用户
	(4)删除用户
	(5)修改用户
2.环境
	Java环境:JDK 1.8.0_181
	Eclipse:neon
	Oracle:Oracle11g
	Mybatis运行环境(jar包):
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.4.6</version>
	</dependency>
	
	加入oracle的驱动jar
	<dependency>	
		<groupId>com.oracle</groupId>
		<artifactId>ojdbc6</artifactId>
		<version>11.2.0.3</version>
	</dependency>
	
	需要手动添加Oracle的驱动jar:
	首先进入ojdbc6.jar所在目录:D:\Oracle\product\11.2.0\dbhome_1\jdbc\lib
	执行命令:mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.3 -Dpackaging=jar -Dfile=ojdbc6.jar
	
3. SqlMapConfig.xml
	配置mabatis    	
<configuration>
	<!-- 配置数据源、事务等mybatis运行环境 -->
	<!--Spring整合后将被废除 -->
	<environments default="development">
		<environment id="development">
			<!-- 配置事务 -->
			<transactionManager type="JDBC" />
			<!-- 配置数据源 -->
			<dataSource type="POOLED">
				<property name="driver" value="oracle.jdbc.OracleDriver" /><!-- 驱动类 -->
				<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" /><!-- 连接路径 -->
				<property name="username" value="user01" /><!-- 用户名 -->
				<property name="password" value="654321" /><!-- 密码 -->
			</dataSource>
		</environment>
	</environments>
	<!-- 加载映射路径 -->
	<mappers>
		<!-- 加载单个映射配置文件 resource属性中包名使用/不是.-->
		<mapper resource="com/it/mapper/UserMapper.xml"/>
	</mappers>
</configuration>

4根据需求操作:用户根据用户id(主键)查询用户信息
第一步 编写实体类

public class User {
	private int id;//用户编号
	private String loginname;//用户名
	private String password;//密码
	private String realname;//真实姓名
	private String sex;//性别
	private String birthday;//生日
	private int dep;//部门编号
	private String email;//邮箱
	private int enabled;//是否可用
	private int createman;//创始人
	private String dname;//部门名称
	private String lasttime;//上次登录时间
	
	@Override
	public String toString() {
		return "User [id=" + id + ", loginname=" + loginname + ", password=" + password + ", realname=" + realname
				+ ", sex=" + sex + ", birthday=" + birthday + ", dep=" + dep + ", email=" + email + ", enabled="
				+ enabled + ", createman=" + createman + ", dname=" + dname + ", lasttime=" + lasttime + "]";
	}
	public String getLasttime() {
		return lasttime;
	}
	public void setLasttime(String lasttime) {
		this.lasttime = lasttime;
	}
	public String getDname() {
		return dname;
	}
	public void setDname(String dname) {
		this.dname = dname;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getLoginname() {
		return loginname;
	}
	public void setLoginname(String loginname) {
		this.loginname = loginname;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getRealname() {
		return realname;
	}
	public void setRealname(String realname) {
		this.realname = realname;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getBirthday() {
		return birthday;
	}
	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}
	public int getDep() {
		return dep;
	}
	public void setDep(int dep) {
		this.dep = dep;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public int getEnabled() {
		return enabled;
	}
	public void setEnabled(int enabled) {
		this.enabled = enabled;
	}
	public int getCreateman() {
		return createman;
	}
	public void setCreateman(int createman) {
		this.createman = createman;
	}
	
}

第二步 映射文件与Mapper接口对应

import java.util.List;

import com.it.bean.User;

public interface UserMapper {
	/**
	 * 根据id查询用户信息
	 * */
	public User selectUserById(int id);
	
	/**
	 * 根据id模糊查询
	 * */
	public List<User> selectUserByLikeName(String name);
	
	/**
	 * 添加用户
	 * */
	public int addUser(User user);
	
	/**
	 * 根据id修改用户密码
	 * */
	public int updatePassword(User user);
	
	/**
	 * 根据用户信息删除用户信息
	 * */
	public int deleteUserById(int id);
}

映射文件命名格式(建议):XXXMapper.xml,例如:UserMapper.xml;

在映射文件中配置SQL语句

<!-- 引入映射配置文件的dtd约束 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace属性:与当前映射配置文件对应的mapper接口的全路径
	建议:映射配置文件和mapper接口的文件名一致,有利于区分当前映射配置文件代替了那个mapper接口的实现类
 -->
<mapper namespace="com.it.mapper.UserMapper">
	<!-- 根据地查询用户信息的SQL语句 
		select标签表示查询
		id属性值:对应表示的mapper接口中的方法名
		将SQL语句封装到MapperStatement的对象中,id可以理解是MapperStatement对象的id
		id是唯一的
		parameterType属性:表示Mapper接口中方法的参数属性,若没有可不写
		resultTypes表示输出结果的类型
		#{}:占位符,相当于?
		#{id}:用来接收输入参数的内容
		
	-->
	<select id="selectUserById" parameterType="int" resultType="com.it.bean.User">
		select * from tuser where id = #{id}
	</select>
	
	<!-- 根据用户名模糊查询用户信息 
		resultType属性:表示单条记录所映射的java对象类型
		${}:表示将接收到的参数内容不添加任何修饰的拼接到SQL语句中
		
		#{}与${}的区别:
		1.#{}表示占位符,防止SQL注入,安全
		2.${}表示拼接SQL串,不能防止SQL注入,不安全
		
		例子:select * from tuser where loginname=#{loginname} and password=#{password}
			若:loginname = adim or 1=1
			select * from tuser where loginname=${loginname} and password=${password}
	-->
	<select id="selectUserByLikeName" parameterType="String" resultType="com.it.bean.User">
		select * from tuser where loginname like '%${value}%'
	</select>
	
	<!-- 新增用户
		parameterType属性中若类型为pojo对象类型,#{}中为对象的属性名
	 -->
	<insert id="addUser" parameterType="com.it.bean.User">
		<!-- selectKey表示主键的生成策略,目前用的是序列
			keyProperty="id" 表示生成的主键赋值给id
			resultType:表生成的主键类型
			order="BEFORE":表示在插入语句前先生成主键值
		 -->
		<selectKey keyProperty="id" resultType="int" order="BEFORE">
			select seq_tuser.nextval from dual
		</selectKey>
		insert into tuser values(#{id},#{loginname},#{password},#{realname},#{sex},#{birthday},#{dep},#{email},1,1,null)
	</insert>
	<!-- 根据id修改用户密码
		
	 -->
	<update id="updatePassword" parameterType="com.it.bean.User" >
		update tuser set password=#{password} where id=#{id}
	</update>
	
	<!-- 根据id删除用户 -->
	<delete id="deleteUserById" parameterType="int">
		delete from tuser where id=#{id}
	</delete>
</mapper>

第三步 在SqlMapConfig.xml文件中加载映射文件

注意:上面已经添加过,下面只是具体展示映射文件的部分

<!-- 加载映射路径 -->
	<mappers>
		<!-- 加载单个映射配置文件 resource属性中包名使用/不是.-->
		<mapper resource="com/it/mapper/UserMapper.xml"/>
	</mappers>

第四步 代码程序测试

import java.io.IOException;
import java.io.Reader;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.it.bean.User;
import com.it.mapper.UserMapper;

public class UserCrud {
	@Test
	public void selectById() throws IOException{
		//加载全局配置文件
		Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
		//根据全局配置文件来创建回话工厂
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
		//根据会话工厂来创建会话对象
		SqlSession session = factory.openSession();
		//获取Mapper接口的代理对象
		UserMapper mapper = session.getMapper(UserMapper.class);
		//调用相应的方法
		User user = mapper.selectUserById(1);
		System.out.println(user);
		//关闭会话
		session.close();
	}
	@Test
	public void selectUsersByName() throws IOException{
		//加载全局配置文件
		Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
		//根据全局配置文件来创建回话工厂
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
		//根据会话工厂来创建会话对象
		SqlSession session = factory.openSession();
		//调用相应
		UserMapper mapper = session.getMapper(UserMapper.class);
		
		List<User> users = mapper.selectUserByLikeName("a");
		//查询
		for(User user: users){
			System.out.println(user);
		}
		//关闭会话
		session.close();
	}
	
	/**
	 * 添加用户
	 * @throws IOException 
	 * 
	 * */
	@Test
	public void addUser() throws IOException{
		//加载全局配置文件
		Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
		//根据全局配置文件来创建回话工厂
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
		//根据会话工厂来创建会话对象
		SqlSession session = factory.openSession();
		//获取Mapper接口的代理对象
		UserMapper mapper = session.getMapper(UserMapper.class);
		//调用相应的方法
		User user = new User();
		user.setLoginname("xiaozhang");
		user.setPassword("123456");
		user.setSex("男");
		user.setBirthday("1997-09-09");
		user.setDep(2);
		user.setRealname("张三");
		user.setEmail("zs@163.com");
		//调用新增用户的值
		int result = mapper.addUser(user);
		if(result>0){
			System.out.println("新增成功!");
		}else{
			System.out.println("新增失败!");
		}
		//提交事务
		session.commit();
		//关闭会话
		session.close();
	}
	
	/**
	 * @throws IOException 
	 * 
	 * */
	@Test
	public void updatePassword() throws IOException{
		//加载全局配置文件
		Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
		//根据全局配置文件来创建回话工厂
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
		//根据会话工厂来创建会话对象
		SqlSession session = factory.openSession();
		//获取Mapper接口的代理对象
		UserMapper mapper = session.getMapper(UserMapper.class);
		//调用相应的修改方法
		User user = new User();
		user.setId(271);
		user.setPassword("654321");
		//
		int result = mapper.updatePassword(user);
		if(result>0){
			System.out.println("密码修改成功!");
		}else{
			System.out.println("密码修改失败!");
		}
		//提交事务
		session.commit();
		//关闭会话
		session.close();
			
	}
	
	/**
	 * 根据id删除用户
	 * @throws IOException 
	 * */
	@Test
	public void deleteUserById() throws IOException{
		//加载全局配置文件
		Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
		//根据全局配置文件来创建回话工厂
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
		//根据会话工厂来创建会话对象
		SqlSession session = factory.openSession();
		//获取Mapper接口的代理对象
		UserMapper mapper = session.getMapper(UserMapper.class);
		//调用相应的修改方法
		User user = new User();
		//
		int result = mapper.deleteUserById(272);
		if(result>0){
			System.out.println("删除成功!");
		}else{
			System.out.println("删除失败!");
		}
		//提交事务
		session.commit();
		//关闭事务
		session.close();
	}
}

可能出现的错误:

SQL语句修改字段与数据库内的字段不符。
pom.xml配置出现问题,常见为下载jar包失败,导致无法找到相关测试文件。
初始化失败,无法找到测试文件:可能的原因有很多,常见为方法名不一致,返回值类型有误,参数列表有误等
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值