Mybatis介绍+简单应用

一、Mybatis快速入门

  1. Mybatis介绍:
    MyBatis是支持普通SQL查询存储过程高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数库中的记录。
    JDBC->DBUtils->MyBatis->Hibernate->SpringData->SpringJDBC->SpringJPA
    1. Mybatis与Hibernate区别:
      1. Hibernate是通过对象得到sql语句;封装比较重,不易对sql优化。
      2. Mybatis是通过sql语句得到对象;轻量级,可以对sql进行优化。
    2. Mybatis实现原理:
      使用java解析xml技术进行解析mybatis.xml,读取jdbc值,进行反射创建数据源。
      创建会话工厂,获取到某个会话工厂的连接,通过命名空间+id在配置文件中找到对应sql语句,使用jdbc执行sql语句,解析xml文件的returnType,使用反射为实体类赋值,得到返回值输出。
  2. Mybatis环境搭建:
    1. 添加maven坐标:
      <dependencies>
      	<dependency>
      		<groupId>org.mybatis</groupId>
      		<artifactId>mybatis</artifactId>
      		<version>3.5.1</version>
      	</dependency>
      	<dependency>
      		<groupId>mysql</groupId>
      		<artifactId>mysql-connector-java</artifactId>
      		<version>8.0.15</version>
      	</dependency>
      </dependencies>
      
    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);
      
    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" />
                      <!-- mysql8以上版本,不加?serverTimezone=GMT,会提示系统时区出现错误 -->
                      <property name="url" value="jdbc:mysql://localhost:3306/architect?serverTimezone=GMT" />
                      <property name="username" value="root" />
                      <property name="password" value="root" />
                  </dataSource>
              </environment>
          </environments>
      </configuration>
      
    4. 定义表的实体类:
      package chauncy.entity;
      
      public class Users {
      	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;
      	}
      
      	@Override
      	public String toString() {
      		return "Users [id=" + id + ", name=" + name + ", age=" + age + "]";
      	}
      	
      	
      }
      
    5. 定义UsersMapper接口:
      package chauncy.mapper;
      
      import chauncy.entity.Users;
      
      public interface UsersMapper {
      	public Users getUsers(int id);
      }
      
    6. 定义操作users表的sql映射文件usersMapper.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="chauncy.mapper.UsersMapper">
      	<select id="getUsers" parameterType="int" resultType="chauncy.entity.Users">
      	   select * from users where id = #{id}
      	</select>
      </mapper>
      
    7. mybatis.xml文件中加载配置文件:
      <mappers>
          <mapper resource="mybatis/usersMapper.xml"/>
      </mappers>
      
    8. mybatis.xml测试方法:
      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 chauncy.entity.Users;
      
      public class TestMybatis {
      	public static void main(String[] args) throws IOException {
      		show();
      	}
      	
      	static	public void show() throws IOException{
      		String resource="mybatis.xml";
      		//读取配置文件
      		Reader resourceAsReader = Resources.getResourceAsReader(resource);
      		//创建session会话工厂
      		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
      		//获取sql会话
      		SqlSession openSession = sqlSessionFactory.openSession();
      		//通过命名空间+id
      		String statement="chauncy.mapper.UsersMapper.getUsers";
      		Users users = openSession.selectOne(statement,1);
      		System.out.println(users.toString());
      		openSession.close();
      	}
      }
      
  3. Mybatis的CUD操作实现:
    1. 增加记录代码实现:
      <insert id="addUsers" parameterType="chauncy.entity.Users"> 
         insert into users(name,age) values(#{name},#{age});
      </insert>
      
      static	public void add() throws IOException{
      	String resource="mybatis.xml";
      	//读取配置文件
      	Reader resourceAsReader = Resources.getResourceAsReader(resource);
      	//创建session会话工厂
      	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
      	//获取sql会话
      	SqlSession openSession = sqlSessionFactory.openSession();
      	//通过命名空间+id
      	String statement="chauncy.mapper.UsersMapper.addUsers";
      	Users addUsers = new Users();
      	addUsers.setName("ChauncyWang");
      	addUsers.setAge(18);
      	//返回影响行数
      	int insert = openSession.insert(statement,addUsers);
      	openSession.commit();
      	System.out.println("insert:"+insert);
      	openSession.close();
      }
      
    2. 修改记录代码实现:
      <update id="updUsers" parameterType="chauncy.entity.Users">
         update users set name=#{name},age=#{age} where id = #{id};
      </update>
      
      static	public void upd() throws IOException{
      	String resource="mybatis.xml";
      	//读取配置文件
      	Reader resourceAsReader = Resources.getResourceAsReader(resource);
      	//创建session会话工厂
      	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
      	//获取sql会话
      	SqlSession openSession = sqlSessionFactory.openSession();
      	//通过命名空间+id
      	String statement="chauncy.mapper.UsersMapper.updUsers";
      	Users updUsers = new Users();
      	updUsers.setId(3);
      	updUsers.setName("chauncy");
      	updUsers.setAge(20);
      	//返回影响行数
      	int update = openSession.update(statement,updUsers);
      	openSession.commit();
      	System.out.println("update:"+update);
      	openSession.close();
      }
      
    3. 删除记录代码实现:
      <delete id="delUsers" parameterType="int">
         delete from users where id = #{id};
      </delete>
      
      static	public void del() throws IOException{
      	String resource="mybatis.xml";
      	//读取配置文件
      	Reader resourceAsReader = Resources.getResourceAsReader(resource);
      	//创建session会话工厂
      	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
      	//获取sql会话
      	SqlSession openSession = sqlSessionFactory.openSession();
      	//通过命名空间+id
      	String statement="chauncy.mapper.UsersMapper.delUsers";
      	int delete = openSession.delete(statement,3);
      	openSession.commit();
      	System.out.println("delete:"+delete);
      	openSession.close();
      }
      

二、SQL注入攻击与防护

  1. 创建表并添加测试数据:
    create table user_table(  
        id      int Primary key,  
        username    varchar(30),  
        password    varchar(30)  
    );  
    insert into user_table values(1,'ChauncyWang1','123456');  
    insert into user_table values(2,'ChauncyWang2','123456'); 
    
  2. SQL注入攻击的产生:
    通过SQL拼接,传入非法条件(例:’ OR 1=1 – )成立。
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**   
     * @classDesc: 功能描述(容易产生SQL注入攻击代码)  
     * @author: ChauncyWang
     * @version: 1.0  
     */  
    public class SqlInjection {
    	public static void main(String[] args) throws SQLException, ClassNotFoundException {
    		String username = "ChauncyWang1";
    		String password = "123456";
    		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:3306/architect?serverTimezone=GMT", "root", "root");
    		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. SQL注入攻击手法:
    将username的值设置为:username=’ ’ OR 1=1 –
    因为–表示SQL注释,因此后面语句忽略;
    因为1=1恒成立,因此 username=’ ’ OR 1=1 恒成立;
  4. SQL注入攻击的解决办法:
    使用?号传参,先编译再执行。
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**   
     * @classDesc: 功能描述(SQL注入攻击)  
     * @author: ChauncyWang
     * @version: 1.0  
     */  
    public class SqlInjection {
    	public static void main(String[] args) throws SQLException, ClassNotFoundException {
    		//注入式攻击方法
    		//String username = "' or 1=1 -- ";
    		String username="' or 1=1 -- ";
    		String password = "123456";
    		/*//拼接SQL的方式,容易产生SQL注入式攻击
    		String sql = "SELECT id,username FROM user_table WHERE " + "username='" + username + "'AND " + "password='"
    						+ password + "'";*/
    		//使用?号方式,进行预编译SQL,防止注入式攻击
    		String sql = "SELECT id,username FROM user_table WHERE username= ? AND password= ?";
    		Class.forName("com.mysql.jdbc.Driver");
    		Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/architect?serverTimezone=GMT", "root", "root");
    		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);
    		}
    	}
    }
    
  5. 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注入的问题。
     代码实现:
    1. 建表
      create table user_table(  
          id      int Primary key,  
          username    varchar(30),  
          password    varchar(30)  
      );  
      insert into user_table values(1,'ChauncyWang1','123456');  
      insert into user_table values(2,'ChauncyWang2','123456');  
      
    2. 定义表的实体类
      package chauncy.entity;
      
      public class UsersTable {
      	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;
      	}
      	@Override
      	public String toString() {
      		return "UsersTable [id=" + id + ", userName=" + userName + ", passWord=" + passWord + "]";
      	}
      	
      	
      }
      
    3. 定义UsersTableMapper接口
      package chauncy.mapper;
      
      import chauncy.entity.UsersTable;
      
      public interface UsersTableMapper {
      	public UsersTable login(UsersTable usersTable);
      	
      }
      
    4. 定义操作usersTable表的sql映射文件usersTableMapper.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="chauncy.mapper.UsersTableMapper">
          <select id="login" parameterType="chauncy.entity.UsersTable" resultType="chauncy.entity.UsersTable">
             select * from users_table where username=${userName} and password=${passWord}
          </select> 
      </mapper>
      
    5. mybatis.xml文件中加载配置文件
      <mappers>
          <mapper resource="mybatis/usersTableMapper.xml"/>
      </mappers>
      
    6. mybatis.xml测试方法
      static public void login() throws IOException{
      	String resource="mybatis.xml";
      	//读取配置文件
      	Reader resourceAsReader = Resources.getResourceAsReader(resource);
      	//创建session会话工厂
      	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
      	//获取sql会话
      	SqlSession openSession = sqlSessionFactory.openSession();
      	//通过命名空间+id
      	String statement="chauncy.mapper.UsersTableMapper.login";
      	UsersTable usersTable = new UsersTable();
      	usersTable.setUserName("'' or 1=1 --");
      	usersTable.setPassWord("'123456'");
      	List<UsersTable> usersTableList = openSession.selectList(statement,usersTable);
      	for (UsersTable usersTable2 : usersTableList) {
      		System.out.println(usersTable2.toString());
      	}
      	openSession.close();
      }
      

三、Mybatis 注解使用

只要使用Mybatis3.0以上就可以使用注解,Mybatis提供了CRUD(增删改查)注解:@insert @delete @update @select

  1. 建立注解Mapper
    package chauncy.mapper;
    
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Select;
    
    import chauncy.entity.Users;
    
    public interface UsersMapper {
    	@Select("select * from users where id=#{id}")
    	public Users getUsers(@Param("id")int id);
    }
    
  2. 加入mybatis.xml
    <mapper class="chauncy.mapper.UsersMapper"/>
    
  3. 运行测试
    public class TestMybatis {
    	public static void main(String[] args) throws IOException {
    		showByAnnocation();
    	}
    	static	public void showByAnnocation() throws IOException{
    		String resource="mybatis.xml";
    		//读取配置文件
    		Reader resourceAsReader = Resources.getResourceAsReader(resource);
    		//创建session会话工厂
    		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
    		//获取sql会话
    		SqlSession openSession = sqlSessionFactory.openSession();
    		UsersMapper usersMapper = openSession.getMapper(UsersMapper.class);
    		Users users = usersMapper.getUsers(1);
    		System.out.println(users.toString());
    		openSession.close();
    	}
    }
    

四、Generator使用

Generator逆向生成对应数据库的实体与dao层,Mybatis的逆向工程使用方法有很多,在此不一一列举。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值