一、目标

Mybatis介绍

Mybatis增删改查

SQL注入问题介绍

Mybatis xml与注解实现

Mybatis分页

二、Mybatis快速入门

2.1 Mybatis介绍

MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数库中的记录.JDBC ->MyBatis

2.2 Mybatis环境搭建

2.2.1添加Maven依赖

    <dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
</dependencies>

2.2.2建表

CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), age INT);
INSERT INTO users(name, age) VALUES('Tom', 12);
INSERT INTO users(name, age) VALUES('Jack', 11);

2.2.3添加mybatis配置文件

<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:23306/mydatabase" />
<property name="username" value="root" />
<property name="password" value="master" />
</dataSource>
</environment>
</environments>
</configuration>

2.2.4定义表的实体类

package com.hongmoshui.mybatis.entity;

public class User
{
private int id; private String name; private int age; public int getId()
{
return id;
} public void setId(int id)
{
this.id = id;
} public String getName()
{
return name;
} public void setName(String name)
{
this.name = name;
} public int getAge()
{
return age;
} public void setAge(int age)
{
this.age = age;
} }

2.2.5定义userMapper接口

package com.hongmoshui.mybatis.mapper;

import com.hongmoshui.mybatis.entity.User;

public interface UserMapper
{
public User getUser(int id); public Integer addUser(String name, int age); public Integer delUser(int id);
}

2.2.6定义操作users表的sql映射文件userMapper.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">
<mapper namespace="com.hongmoshui.mybatis.mapper.UserMapper">
<select id="getUser" parameterType="int"
resultType="com.hongmoshui.mybatis.entity.User">
SELECT * FROM users where id =#{id}
</select>
<insert id="addUser"
parameterType="com.hongmoshui.mybatis.entity.User">
INSERT INTO users(name, age) VALUES(#{name}, #{age});
</insert>
<delete id="delUser" parameterType="int">
delete from users where id=#{id}
</delete> </mapper>

2.2.7mybatis.xml文件中加载配置文件

    <mappers>
<mapper resource="mapper/userMapper.xml" />
</mappers>

2.2.8mybatis测试方法

package com.hongmoshui.mybatis;

import java.io.IOException;
import java.io.Reader; 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 com.hongmoshui.mybatis.entity.User; public class TestMybatis
{
public static void main(String[] args) throws IOException
{
String resource = "mybatis.xml";
// 读取配置文件
Reader reader = Resources.getResourceAsReader(resource);
// 获取会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession openSession = sqlSessionFactory.openSession();
addUser(openSession);
delUser(openSession);
getUser(openSession);
} private static void getUser(SqlSession openSession)
{
// 查询
String sql = "com.hongmoshui.mybatis.mapper.UserMapper.getUser";
// 参数id
int id = 1;
// 调用api查询
User user = openSession.selectOne(sql, id);
System.out.println(user.toString());
} private static void addUser(SqlSession openSession)
{
// 新增SQL
String sql = "com.hongmoshui.mybatis.mapper.UserMapper.addUser";
// 调用api查询
User user = new User();
user.setAge(19);
user.setName("hongmoshui");
int reuslt = openSession.insert(sql, user);
openSession.commit();
System.out.println(reuslt); } private static void delUser(SqlSession openSession)
{
// 删除SQL
String sql = "com.hongmoshui.mybatis.mapper.UserMapper.delUser";
// 调用api查询
int id = 2;
int reuslt = openSession.insert(sql, id);
openSession.commit();
System.out.println(reuslt); }
}

三、sql注入案例

3.1创建表+测试数据

create table user_table(
id int Primary key,
username varchar(30),
password varchar(30)
);
insert into user_table values(1,'hongmoshui-1','');
insert into user_table values(2,'hongmoshui-2','');

3.2 jdbc进行加载

package com.hongmoshui.mybatis;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class TestSQL
{
public static void main(String[] args) throws ClassNotFoundException, SQLException
{
String username = "hongmoshui-1";
String password = "12345";
String sql = "SELECT id,username FROM user_table WHERE " + "username='" + username + "'AND " + "password='" + password + "'";
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:23306/mydatabase", "root", "master");
PreparedStatement stat = con.prepareStatement(sql);
System.out.println(stat.toString());
ResultSet rs = stat.executeQuery();
while (rs.next())
{
String id = rs.getString(1);
String name = rs.getString(2);
System.out.println("id:" + id + ",name:" + name);
}
} }

3.3将username的值设置为

username='  OR 1=1 -- 或者username or 1='1

因为--表示SQL注释,因此后面语句忽略;

因为1=1恒成立,因此 username='' OR 1=1  恒成立,因此SQL语句等同于:

SELECT id,username FROM user_table

3.4sql注入解决办法

第一步:编译sql

第二步:执行sql

优点:能预编译sql语句

package com.hongmoshui.mybatis;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class TestSQL
{
public static void main(String[] args) throws ClassNotFoundException, SQLException
{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:23306/mydatabase", "root", "master");
// 无注入情况
String username1 = "hongmoshui-1";
String password1 = "12345";
String sql1 = "SELECT id,username FROM user_table WHERE " + "username='" + username1 + "'AND " + "password='" + password1 + "'";
selectNoInjection(con, username1, password1, sql1);
// 注入,但是有预编译
String username2 = "username=' OR 1=1 -- ";
String password2 = "12345";
String sql2 = "SELECT id,username FROM user_table WHERE username=? AND password=?";
selectInjection(con, username2, password2, sql2); } private static void selectInjection(Connection con, String username, String password, String sql) throws SQLException
{
PreparedStatement stat = con.prepareStatement(sql);
stat.setString(1, username);
stat.setString(2, password);
System.out.println(stat.toString());
ResultSet rs = stat.executeQuery();
while (rs.next())
{
String id = rs.getString(1);
String name = rs.getString(2);
System.out.println("id:" + id + "---name:" + name);
}
} private static void selectNoInjection(Connection con, String username, String password, String sql) throws ClassNotFoundException, SQLException
{
PreparedStatement stat = con.prepareStatement(sql);
System.out.println(stat.toString());
ResultSet rs = stat.executeQuery();
while (rs.next())
{
String id = rs.getString(1);
String name = rs.getString(2);
System.out.println("id:" + id + ",name:" + name);
}
} }

3.4 mybatis中#与$区别

动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析。mybatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${}。

在下面的语句中,如果 username 的值为 zhangsan,则两种方式无任何区别:

select * from user where name = #{name};
select * from user where name = ${name};

其解析之后的结果均为

select * from user where name = 'zhangsan';

但是 #{} 和 ${} 在预编译中的处理是不一样的。#{} 在预处理时,会把参数部分用一个占位符 ? 代替,变成如下的 sql 语句:

select * from user where name = ?;

而 ${} 则只是简单的字符串替换,在动态解析阶段,该 sql 语句会被解析成

select * from user where name = 'zhangsan';

以上,#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。

那么,在使用过程中我们应该使用哪种方式呢?

答案是,优先使用 #{}。因为 ${} 会导致 sql 注入的问题。看下面的例子:

 select * from ${tableName} where name = #{name}

在这个例子中,如果表名为

user; delete user; --

  则动态解析之后 sql 如下:

select * from user; delete user; -- where name = ?;

  --之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成重大损伤,极大可能导致服务器宕机。

但是表名用参数传递进来的时候,只能使用 ${} ,具体原因可以自己做个猜测,去验证。这也提醒我们在这种用法中要小心sql注入的问题。

3.4.1创建UserTable

package com.hongmoshui.mybatis;

public class UserTable
{
private int id; private String userName; private String passWord; public int getId()
{
return id;
} public void setId(int id)
{
this.id = id;
} public String getUserName()
{
return userName;
} public void setUserName(String userName)
{
this.userName = userName;
} public String getPassWord()
{
return passWord;
} public void setPassWord(String passWord)
{
this.passWord = passWord;
} }

3.4.2创建UserTableMapper

package com.hongmoshui.mybatis.mapper;

import com.hongmoshui.mybatis.UserTable;

public interface UserTableMapper
{
public UserTable login(UserTable userTable);
}

3.4.3userTableMapper.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">
<mapper namespace="com.hongmoshui.mybatis.mapper.UserTableMapper">
<select id="login"
parameterType="com.hongmoshui.mybatis.UserTable"
resultType="com.hongmoshui.mybatis.UserTable">
SELECT id ,username as userName FROM user_table WHERE
username=${userName} AND password=${passWord}
</select> </mapper>

3.4.4 mybatis.xml文件中加载配置文件

    <mappers>
<!-- <mapper resource="mapper/userMapper.xml" /> -->
<mapper resource="mapper/userTableMapper.xml" />
</mappers>

3.4.5 测试SQL注入

package com.hongmoshui.mybatis;

import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;
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; public class TestLoginMybatis3
{ public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException
{ String resource = "mybatis.xml";
// 读取配置文件
Reader reader = Resources.getResourceAsReader(resource);
// 获取会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession openSession = sqlSessionFactory.openSession();
// 查询
String sql = "com.hongmoshui.mybatis.mapper.UserTableMapper.login";
// 调用api查询
UserTable userTable = new UserTable();
userTable.setUserName("'' OR 1=1 -- ");
userTable.setPassWord("12345");
List<UserTable> listUserTable = openSession.selectList(sql, userTable);
for (UserTable ub : listUserTable)
{
System.out.println(ub.getUserName());
}
}
}

3.4.6 总结

优先使用 #{}。因为 ${} 会导致 sql 注入的问题

一、Mybatis 注解使用

Mybatis提供了增删改查注解、@select @delete @update

4.1 建立注解Mapper

package com.hongmoshui.mybatis.mapper;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; import com.hongmoshui.mybatis.UserTable; public interface UserTestMapper {
@Select("select * from user_table where id = ${id};")
public UserTable getUser(@Param("id") int id);
}

4.2 加入mybatis.xml

    <mappers>
<!-- <mapper resource="mapper/userMapper.xml" />
<mapper resource="mapper/userTableMapper.xml" /> -->
<mapper class="com.hongmoshui.mybatis.mapper.UserTestMapper" />
</mappers>

4.3 运行测试

package com.hongmoshui.mybatis;
import java.io.IOException;
import java.io.Reader;
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 com.hongmoshui.mybatis.mapper.UserTestMapper; public class TestMybatis3
{
public static void main(String[] args) throws IOException
{
String resource = "mybatis.xml";
// 读取配置文件
Reader reader = Resources.getResourceAsReader(resource);
// 获取会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession openSession = sqlSessionFactory.openSession();
// 调用api查询
UserTestMapper userTestMapper = openSession.getMapper(UserTestMapper.class);
System.out.println(userTestMapper.getUser(2));
}
}

【学习】017 Mybatis框架的更多相关文章

  1. Mybatis框架学习总结-Mybatis框架搭建和使用

    Mybatis介绍 Mybatis是一个支持普通SQL查询,存储过程,和高级映射的优秀持久层框架.Mybatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.Mybatis可以使 ...

  2. 框架学习系列 mybatis mapper映射文件之输出映射

    1: mapper映射文件输出映射(输入类型) 2:resultType的使用 3:resultMap的使用 3:总结&下节预告 本文是<凯哥陪你学系列-框架学习之mybatis框架学习 ...

  3. Mybatis框架-update节点元素的使用

    今天我们学习一下mybatis框架中的update节点元素的使用 需求:修改用户表中的一条数据记录,修改编号为21的用户的密码 UserMapper.xml UserMapper.java 编写测试方 ...

  4. Spring MVC 学习总结(十)——Spring+Spring MVC+MyBatis框架集成(IntelliJ IDEA SSM集成)

    与SSH(Struts/Spring/Hibernate/)一样,Spring+SpringMVC+MyBatis也有一个简称SSM,Spring实现业务对象管理,Spring MVC负责请求的转发和 ...

  5. 【MyBatis学习01】宏观上把握MyBatis框架

    今天开始学习mybatis框架,博客主要记录学习过程中的一些总结,如有错误之处,欢迎留言指正~先用mybatis的鸟鸟来镇个楼,咳咳~~ mybatis框架是一个持久层框架,是Apache下的顶级项目 ...

  6. (转)MyBatis框架的学习(七)——MyBatis逆向工程自动生成代码

    http://blog.csdn.net/yerenyuan_pku/article/details/71909325 什么是逆向工程 MyBatis的一个主要的特点就是需要程序员自己编写sql,那么 ...

  7. (转)MyBatis框架的学习(六)——MyBatis整合Spring

    http://blog.csdn.net/yerenyuan_pku/article/details/71904315 本文将手把手教你如何使用MyBatis整合Spring,这儿,我本人使用的MyB ...

  8. (转)MyBatis框架的学习(五)——一对一关联映射和一对多关联映射

    http://blog.csdn.net/yerenyuan_pku/article/details/71894172 在实际开发中我们不可能只是对单表进行操作,必然要操作多表,本文就来讲解多表操作中 ...

  9. (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql

    http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...

随机推荐

  1. php 的路由简介 (一个简单的路由模式)

    <?php $_SERVER['REQUEST_URI'] = '/post/edit/1024?foo=bar'; $uri = explode('/', parse_url($_SERVER ...

  2. send()/ recv() 和 write()/ read()

    Linux下数据的接收和发送write()/ read() Linux 不区分套接字文件和普通文件,使用 write() 可以向套接字中写入数据,使用 read() 可以从套接字中读取数据. 两台计算 ...

  3. node.js npm 操作 模块化开发 cnpm镜像安装

    模块(包) 传统引入 js 的缺点 整个网页,我们写了一个 js 文件,所有的特效都在里面 耦合度太高,代码之间关联性太强,不便于后期维护 变量容易 全局污染 如果将 复杂的 js 文件,拆成多个功能 ...

  4. HDU6025 Coprime Sequence(gcd)

    HDU6025 Coprime Sequence 处理出数列的 \(gcd\) 前缀和后缀,删除一个数后的 \(gcd\) 为其前缀和后缀的 \(gcd\) . 遍历数列取 \(max\) 即为答案. ...

  5. Hook基本知识

    一.什么是HOOK(钩子) Windows系统,建立在事件驱动机制上,就是整个系统都是通过消息传递实现的.hook(钩子)是一种特殊的消息处理机制,它可以监视系统或者进程中的各种事件消息,截获发往目标 ...

  6. 二、Python基础

    1.变量名 数字,字母,下划线:aaa1;aa_b1 不能以数字开头:1aa 变量名不能是python内部的关键字 2.getpass import getpass username=raw_inpu ...

  7. WCF 出现System.Core version 2.0.5.0 未能加载问题

    Window server 2008 R2 Enterprise 版本测试: 需要安装Net补丁: NDP40-KB2468871-v2-x64 下载地址 https://www.microsoft. ...

  8. 别把&和nohup混为一谈, 根本不是同一个东西好不好 ------ 聊聊./a.out & , nohut ./a.out , nohup ./a.out &的区别

    在第一家公司工作的时候, 我认识了&,在第二家公司工作的时候, 我认识了nohup,  这就是渊源.  随后, 我就一直糊涂用他们, 但并不懂这两个东西. 网上很多地方是乱扯, 瞎复制, 为什 ...

  9. Redis-集群操作

    一.查看集群状态 1.查看集群状态 /opt/redis/src/redis-cli -h 本机IP -p redsi实例端口 -c #连接redis实例 /opt/redis/src/redis-c ...

  10. 第五周课程总结&试验报告(三

    实验三 String类的应用 实验目的 掌握类String类的使用: 学会使用JDK帮助文档: 实验内容 1.已知字符串:"this is a test of java".按要求执 ...