Mybatis框架--第一天

为什么要学Mybatis

解决传统JDBC存在的问题(括号中是mybatis的解决方法)

1.sql语句的硬编码问题(通过映射文件将sql写入到xml文件中)

2.数据库连接编码问题(全局文件的environments中的environment中配置datasource)

3.查询结果的封装 (映射文件的resultType,解决之前通过jdbc封装,利用反射实现的结果,无法解决多表查询的封装和不同命的结果封装)

4.频繁的获取连接(数据库)

正是因为传统的JDBC存在以上这些问题,而这些问题Mybatis框架都得到了解决,因此我们就要学习Mybatis


一、Mybatis是什么?

Mybatis是java的一个轻量级半ORM的持久化框架。

ORM:对象关系模型  
  Hibernate:HQL语句 将表通过关系映射,映射为实体类,我们对实体类进行的CRUD操作,Hibernate根据数据库方言将HQL语句翻译成对应的SQL语句。入门难,精通更难
  Mybatis(半ORM框架):前身Ibatis,入门容易,精通容易
  MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code(源码托管平台),并且改名为MyBatis。2013年11月迁移到Github。
 Mybatis-plus:增强版的Mybatis
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。

mybatis的官方文档:mybatis – MyBatis 3 | 简介


二、Mybatis的运行原理

1.Mybatis的核心文件分为两种,一种为全局配置文件:主要配置数据库、连接信息、别名、插件、加载映射文件等相关信息。第二种文映射文件,主要包含sql,输出参数,查询结果映射类型

2.SqlSessionFactoryBuilder通过build()方法加载配置文件从而生成SqlSessionFactory

3.SqlSessionFactory通过openSession()方法获取到SqlSession对象

4.SqlSession提供给开发人员用于操作数据库的所以方法。如SelectOne SelectList等方法

5.SqlSession调用executor执行器(简单执行器和缓存执行器)

6.executor调用MapperStatement对象(sql),包含有输入参数和输出结果

7.输入参数和输出参数只能包含(简单数据类型、自定义POJO类型、HashMap类型)

三、Mybatis的入门程序

  1.下载或者添加依赖

mybats-xxx.jar
mysql-connector-java.jar 

 2.创建全局配置文件

<?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>

<!-- 设置相关信息 -->
 <settings>  
   <!-- 配置日志文件log4J --> 
<setting name="logImpl" value="LOG4J" />
</settings>

   
   <!-- 环境  配置数据源以及事务的方式  复数形式,可以配置多个数据库连接环境  default 默认采用的环境  将id写入default--> 
   <environments default="dev">
   <!--开发环境 dev  -->
        <environment id="dev">
        <!-- type 选择mybatis支持的事务类型  JDBC选择jdbc的事务支持 或者Managed非事务的形式    -->
           <transactionManager type="JDBC"></transactionManager>
           <!-- 数据源 type类型 POOLED 采用连接池形式 采用了Mybatis自身的连接池   Mybatis自带的连接池性能比较差  
                                                          springboot连接池、 druid、  c3p0
                               UNPOOLED采用非连接池形式
                               JNDI java目标命名服务 -->
           <dataSource type="POOLED">
           <!-- name 属性名  value对应的值 -->
               <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"/>
               <property name="username" value="root"/>
               <property name="password" value="root"/>
           </dataSource>
        </environment>
       
              <!--生产环境 prod  -->
        <environment id="prod">
          <transactionManager type="JDBC"></transactionManager>
          <dataSource type="POOLED">
               <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql:///test"/>
               <property name="username" value="root"/>
               <property name="password" value="root"/>
          </dataSource>
        </environment>
   </environments>
   
   <!--加载映射文件  -->
   <mappers>
   <!-- 单个映射文件加载   resource 映射文件的位置 是基于classpath的  -->
      <mapper resource="a.xml"></mapper>
   </mappers>
</configuration>

3.创建映射文件 

<?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">
<!-- 命名空间 就相当于package  作用是保证不同的映射文件中可以有相同的sql id -->
  <mapper namespace="a">
  
      <!-- 查询总的用户数 -->
      <!-- select标签中只能写select  id是唯一标识   单个映射文件中不能出现相同的id 
        reusltType:结果的映射类型
      -->
      <select id="selectUserCount"   resultType="int">
         select count(*) from account
      </select>
  </mapper>

4.从xml中构建sqlSessionFactory

package com.sofwin.daili;

import java.io.IOException;
import java.io.InputStream;

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 jdk.nashorn.internal.runtime.regexp.joni.Config;

public class Test01 {
	public static void main(String[] args) throws IOException {
		SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
		//mybatis中 提供 Resources方法  从类路径下读取资源
		InputStream is=Resources.getResourceAsStream("config.xml");
		SqlSessionFactory factory = builder.build(is);
		SqlSession sqlSession = factory.openSession();
		//返回结果是 人员类型
		//输入参数   statement ==mapperstatement的id=namespace的id
		Integer num = sqlSession.selectOne("a.selectUserCount");
		System.out.println(num);
	}

}

四、生命周期 

1.SqlSessionFactoryBuilder(静态代码块中)

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

2.SqlSessionFactory(静态成员变量)  

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。(单例)

3.SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。

五、传统的Mybatis的DAO模式

工具类

DAO接口

DAO的实现

实体类

  1.工具类

public class SqlSessionUtil {
private static SqlSessionFactoryfactory;
static {
    SqlSessionFactoryBuilder build =
    new SqlSessionFactoryBuilder();
    try {
      InputStream is =
      Resources.getResourceAsStream("configer.xml");
      factory = build.build(is);
    } catch (IOException e) {
       e.printStackTrace();
    }
}

public static SqlSession getSession() {
   // 事务默认没有自动提交  
   return factory.openSession();
   }
}

2.实体类

package com.sofwin.pojo;

public class Account {
   private String name ;
   private Integer money;
	
   public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getMoney() {
		return money;
	}
	public void setMoney(Integer money) {
		this.money = money;
	}
   
}

3.dao接口 

package com.sofwin.dao;

import java.util.List;

import com.sofwin.pojo.Account;

public interface AccountDao {
	
	  /**
	   * 向用户表中插入数据
	   * @param account  用户的实体类
	   * @return   影响的行数
	   */
		int insert(Account account);
		
		/**
		 * 修改
		 * @param account 用户的实体类
		 * @return 影响的行数
		 */
		int update(Account account);
		
		/**
		 * 通过名称进行删除
		 * @param name  名称
		 * @return   影响的行数
		 */
		int deleteByName(String name);
		
		/**
		 * 获取用户中的所有信息
		 * @return  用户的集合
		 */
		List<Account> selectAccounts();
		
		/**
		 * 通过名称来获取单个用户信息
		 * @param name  名称
		 * @return  单个用户
		 */
		Account selectByName(String name);
		
		}
	
	   

4.dao接口的实现类 

package com.sofwin.dao.impl;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.sofwin.dao.AccountDao;
import com.sofwin.pojo.Account;
import com.sofwin.util.SqlSessionUtil;

public class AccountDaoImpl  implements AccountDao{
	 /**
	   * 向用户表中插入数据
	   * @param account  用户的实体类
	   * @return   影响的行数
	   */
	@Override
	public int insert(Account account) {
		SqlSession session =SqlSessionUtil.getSqlSession();
	    int flag=session.insert("account.insert",account);
		return flag;
	}
	/**
	 * 修改
	 * @param account 用户的实体类
	 * @return 影响的行数
	 */
	@Override
	public int update(Account account) {
		SqlSession session =SqlSessionUtil.getSqlSession();
	    int flag=session.update("account.update",account);
		return flag;
	}
	/**
	 * 通过名称进行删除
	 * @param name  名称
	 * @return   影响的行数
	 */
	@Override
	public int deleteByName(String name) {
		SqlSession session =SqlSessionUtil.getSqlSession();
	    int flag=session.delete("account.delete",name);
		return flag;
	}
	
	/**
	 * 获取用户中的所有信息
	 * @return  用户的集合
	 */
	@Override
	public List<Account> selectAccounts() {
		SqlSession session =SqlSessionUtil.getSqlSession();
	   return session.selectList("account.selectAll");
	}
	/**
	 * 通过名称来获取单个用户信息
	 * @param name  名称
	 * @return  单个用户
	 */
	@Override
	public Account selectByName(String name) {
		SqlSession session =SqlSessionUtil.getSqlSession();
		   return session.selectOne("account.selectOne",name);
		
	}

	
	
	
}

5.全局配置和映射文件 

<?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>
  
    
     
    <settings>
      
       <setting  name="logImpl" value="LOG4J2"/>
    </settings>
      
      <!-- 配置环境  default是默认的环境是 -->
    <environments default="dev">
        <!-- 这里写多种环境  这里我就写一种  其他的环境是相同的 -->
      <environment id="dev">
          <!-- 设置事务的管理者   一般是JDBC的事务管理     或者是Manage非事务管理的形式 -->
         <transactionManager type="JDBC"></transactionManager>
         <!-- 配置数据源的类型  POOLED池化类型 -->
         <dataSource type="POOLED">
             <!-- name是属性  value是值 -->
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!-- serverTimezone=UTC是设置时区 -->
            <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
         </dataSource>
      </environment>
   </environments>
   
   <!-- 加载映射文件   因为io流只能操作一个 根据特点 全局配置文件只有一个 而映射文件可以有多个   因此我们在这里加载映射文件  到时候只需要加载全局配置文件即可 -->
   <mappers>
      <!--这个地址是基于classPath的 -->
        <mapper resource="Mapper.xml"></mapper>
   </mappers>
  </configuration>

<?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">
<!-- 命名空间 就相当于package  作用是保证不同的映射文件中可以有相同的sql id -->
  <mapper namespace="account">
  
      <!-- 查询总的用户数 -->
      <!-- select标签中只能写select  id是唯一标识   单个映射文件中不能出现相同的id 
        reusltType:结果的映射类型
      -->
       <select id="selectAccountCount"   resultType="int">
         select count(*) from account
      </select>
      
      <insert id="insert"   parameterType="com.sofwin.pojo.Account">
       insert into account(name,money) values(#{name},#{money})
     </insert>
      
      
      <update id="update"  parameterType="com.sofwin.pojo.Account">
        update account set money=#{money} where name=#{name}
      </update>
      
      <delete id="delete"  parameterType="java.lang.String" >
       delete from account where name=#{name}
      </delete>
      
      <select id="selectAll" resultType="com.sofwin.pojo.Account"  > 
         select * from account
      </select>
      
      
      <select id="selectOne" resultType="com.sofwin.pojo.Account"   parameterType="java.lang.String"  > 
         select * from account where name=#{name}
      </select>
      
      
  </mapper>

6.测试类 

package com.sofwin.daili;

import java.util.List;

import com.sofwin.dao.AccountDao;
import com.sofwin.dao.impl.AccountDaoImpl;
import com.sofwin.pojo.Account;

public class Demo0001 {

	public static void main(String[] args) {
		//创建dao对象
		AccountDao  dao=new AccountDaoImpl();
		//创建account对象
		Account account=new Account();
		account.setName("lisi");
		account.setMoney(20000);
		System.out.println(account);
//		dao.insert(account);
//		dao.update(account);
		
		dao.deleteByName("zhangsan");
//	   Account selectAccounts = dao.selectByName("lisi");
//		System.out.println(selectAccounts);
	}

}

六、SqlSession的API 

方法参数描述
selectOnestatment,OBject(占位符需要的值)查询语句,sql语句得出的结果行数<=1

selectList

sql语句的执行结果没有要求
insertstatment,OBject(占位符需要的值)调用insert语句,返回结果影响行数
commit手动提交事务
updatastatment,OBject(占位符需要的值)执行updata语句,返回影响行数
deletestatment,OBject(占位符需要的值)执行delete语句,返回影响行数
getMapperClass通过类对象获取代理对象

总结:

  #{}为占位符,当输入参数是简单类型时,  #{}中为任意字符

                         当输入参数是自定义的POJO类型的时候,#{}中为自定义类型的属性名

                         当输入参数为map类型时,#{}中放入key

  ${}为占位符,当输入参数是简单类型时, ${}中为value

                         当输入参数是自定义的POJO类型的时候, ${}中为自定义类型的属性名

                         当输入参数为map类型时, ${}中放入key

七、Mybatis的调试

主要常用的第三方有

1.log4j 

通过日志进行调试,需要整合第三方日志
 commons-logging 
 log4j 
 src创建log4j.properties配置文件(配置日志)

log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout =
org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout =
org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPa
ttern = [%-5p] %d{yyyy-MM-dd
HH:mm:ss,SSS} method:%l%n%m%n

2.log42

commons-logging
log4j-core 
log4j-api 

创建log4j2.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!--status:Log4j2内部日志的输出级别,设置为
TRACE对学习Log4j2非常有用 -->
<!--monitorInterval:定时检测配置文件的修改,有
变化则自动重新加载配置,时间单位为秒,最小间隔为5s
-->
<Configuration status="debug"
monitorInterval="600">
<!--Appenders:定义日志输出目的地,内容和格
式等 -->
<Appenders>
<!--Console:日志输出到控制台标准输出
-->
<Console name="Console"
target="SYSTEM_OUT">
<!--pattern:日期,线程名,日志级
别,日志名称,日志信息,换行 -->
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t]
%-5level [%L] - %msg%n" />
</Console>
</Appenders>
<!--Loggers:定义日志级别和使用的
Appenders -->
<Loggers>
<!--Root:日志默认打印到控制台 -->
<!--level日志级别: ALL < TRACE <
DEBUG < INFO < WARN < ERROR < FATAL < OFF
-->
<Root level="DEBUG">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>

3.Logback

最后在全局配置的xml文件的settings中设置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值