Afternoon of the sixth day of javaweb training-Mybatis basics

Mybatis basics

1. Course introduction

  1. Why do you need Mybatis; (understand)
  2. First met Mybatis; (understand)
  3. Introduction to Mybatis; (Master)
  4. Mybatis tools; (master)
  5. Mapper mapper; (master)
  6. Mybatis use details; (master)
    SSM framework: Spring + springmvc + mybatis [configuration]-note
    a change in the dao layer code: reason: focus

2. Why do you need Mybatis

1. Look at a piece of code written by JDBC:

Insert picture description here

2. Questions:
(1) SQL is written in JAVA code, the code must be modified to modify SQL, and the coupling is too high;
(2) There is too much code and too much repetitive code;
(3) Manually set parameters, and if it is a query operation , You also need to manually convert the results, which is troublesome;
(4) The connection resources are manually closed, which is troublesome [after integrating with Spring, you do not need to manually close the connection];

3. First acquainted with Mybatis

3.1. What is Mybatis

1. MyBatis is an ORM database persistence framework;
2. The bottom layer of Mybatis is still native JDBC code, which encapsulates the JDBC code;

3.1.1. What is a framework

  1. Framework (Framework) is a frame: refers to itsBinding. It is also a shelf: refers to its support;
  2. The framework in the program specifically refers to a constrained supporting structure designed to solve an open problem. In this structure, more components can be expanded and inserted according to specific problems, so that a complete solution to the problem can be constructed more quickly and conveniently;
  3. The framework in the program is actually a combination of a series of jar packages (a series of .class files);
  4. The framework is a semi-finished product and does not solve specific problems, but after the framework is established, there is no need to start from scratch, which improves development efficiency;
  5. The framework is usually created to solve a problem in a certain field;
  6. It is suitable for team development, unified specifications and convenient maintenance; in
    summary: the so-called framework is some supporting structures provided, through these supporting structures, specific problems can be solved, but certain specifications must be followed in the use process;

3.1.2. What is database persistence

  1. Data persistence is to convert the data model in memory to a storage model, that is, save the data in memory to the database;
  2. Common data persistence is divided into disk persistence and database persistence;
  3. The simplest way in Java is to use native jdbc code to complete database persistence, but this method has many problems;

3.1.3. What is ORM

ORM: Object Relational Mapping (ORM): It is a technology to solve the mismatch between object-oriented and relational databases;

3.1.3.1. ORM framework mapping method

There are many ways to manipulate database relationships in ORM framework, and there are two commonly used methods: the
first: SQL operation mode (semi-mapping or semi-automatic): configure SQL in the configuration file, and complete the conversion between object entities and database relationships in different SQLs Operation (how to implement Mybatis)

Insert picture description here

The second: complete mapping: directly use the object entity and database relationship for mapping, without writing SQL (simple operation), generated by the framework itself (JPA, Hibenate implementation)

Insert picture description here

3.1.3.2. ORM principle

  1. Use a certain mapping method to map the entity model and the database relationship;
  2. Load these mappings and database configuration files to connect to the database when the ORM framework starts;
  3. ORM encapsulates the most native jdbc and provides a more convenient operation API;
  4. Dao uses the convenient API provided by ORM to manipulate database relationships in an object manner;
Insert picture description here

3.1.3.3. Common ORM persistence framework

  1. JPA: It is an ORM specification, not an ORM framework. It is implemented by major ORM frameworks;
  2. Hibernate (complete mapping): The currently popular ORM framework, with smart design, average performance (control performance by yourself, not very good control), and rich documentation. Hibernate is a complete ORM framework, we don't need to write a sentence of SQL for conventional CRUD;
  3. MyBatis (semi-mapping): This is an open source project iBatis of Apache. The persistence layer framework provided includes SQL Maps (Mapper) and Dao, allowing developers to write SQL directly, which is more flexible;

3.2. `The origin of Mybatis

  1. Mybatis was originally an open source project iBatis of apache. In 2010, this project was migrated from apache software foundation to google code, and was renamed MyBatis. Migrated to Github in November 2013;
  2. The term iBatis comes from the combination of "internet" and "abatis", which is a Java-based persistence layer framework;
  3. Mybatis includes SQL Maps (Mapper) and Dao;

3.3. Advantages of Mybatis

  1. The sql statement is separated from the code and stored in the xml configuration file for easy maintenance;
  2. Mybatis eliminates almost all JDBC code and manual setting of parameters and retrieval of result sets;
  3. Provide XML tags, support writing dynamic SQL, instead of writing logic code;

Interview questions: What are the advantages of Mybatis compared to jdbc?
1. Extract the sql statement from the java code for easy maintenance, and there is no need to modify the java code when modifying the sql;
2. There is no need to manually set the parameters and process the result set, which makes it easier for us to operate the database;
3. Compared with JDBC , Which greatly reduces the amount of code and improves development efficiency;

4. Getting started with MyBatis

4.1. Import the corresponding jar package

Insert picture description here

4.2. Prepare the corresponding table

Insert picture description here

4.2.1. Prepare the corresponding domain

1. Create a Product object, corresponding to the database table
2. The name and type of the class are matched with our product table

public class Product {
	private	Long id;
	//商品名称
	private String productName;
	//品牌
	private String brand;
	//供应商
	private String supplier;
	//零售价
	private BigDecimal salePrice;
	//进价
	private BigDecimal costPrice;
	//折扣价
	private Double cutoff;
	//商品分类编号
	private Long dir_id;
	 
   //提供getter与setter...
}

4.2.2. DAO layer preparation of product

Interface and empty implementation class

Insert picture description here
/**
 * 商品的持久操作
 * @author Administrator
 */
public interface IProductDAO {
	/**
	 * 添加一个商品
	 */
	void save(Product p);
	
	/**
	 * 更新一个商品
	 */
	void update(Product p);
	
	/**
	 * 删除一个商品
	 */
	void delete(Long id);
	
	/**
	 * 得到一个商品
	 */
	Product get(Long id);
	/**
	 * 得到所有商品
	 */
	List<Product> findAll();
}

4.2.3. Test first

It’s a good habit to write code to test

Insert picture description here

4.3. Getting started

4.3.1. Analysis of implementation steps

everything's ready. The next step is to start using MyBatis. But here is the question, how to use it?
Check the document: Although the document has only more than 50 pages, it is enough for us to study.

  1. Let’s enter the door first: start with the introduction. After introducing what MyBatis is, we are talking about a core object: SqlSessionFactory. Next, we have to find ways to get this core object;
  2. Then how to get the SqlSessionFactory object: directly find the section in the document to build SqlSessionFactory from XML and start;
  3. To obtain SqlSessionFactory, we need to prepare a core Mybatis-config.xml file, and then create it through SqlSessionFactoryBuilder, so the steps:
    (1) Create the Mybatis core configuration file (Mybatis-config.xml), and configure the environment;
    (2) Load The core configuration file
    (3) creates a SqlSessionFactoryBuilder object;
    (4) Constructs a SqlSessionFactory object through the SqlSessionFactoryBuilder object
    (5) Creates a Mapper mapping file and configures it;
    (6) Obtains SqlSession through SqlSessionFactory to execute mapping SQL

4.3.2. Implementation

核心配置文件:MyBatis-Config.xml
<configuration>
    <!-- 引入配置文件信息,这里不能加classpath:。
		resource:引入类路径下的资源,即classpath,所以不需要写classpath:
		url:引入网络路径或磁盘路径下的资源 
	-->
	<properties resource="db.properties"></properties>
	<!-- 环境们 (很多环境的意思)
		default:默认使用哪一个环境(必需对应一个环境的id)
	 -->
	<environments default="development">
		<!-- 一个环境  id:为这个环境取唯一一个id名称 -->
		<environment id="development">
			<!-- 事务管理   type:JDBC(支持事务)/MANAGED(什么都不做) -->
			<transactionManager type="JDBC" />
			<!-- 数据源, 连接池  type(POOLED):MyBatis自带的连接池 -->
			<dataSource type="POOLED">
				<!-- 连接数据库的参数:直接写死的方式 -->
                <!--
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql:///mydb" />
				<property name="username" value="root" />
				<property name="password" value="admin" />
                 -->
                <!-- 连接数据库的参数:使用属性文件的方式 -->
                <property name="driver" value="${db.driver}" />
				<property name="url" value="${db.url}" />
				<property name="username" value="${db.username}" />
				<property name="password" value="${db.password}" />
			</dataSource>
		</environment>
	</environments>
   <!-- 这个mappers代表的是相应的ORM映射文件 -->
	<mappers> 
		<mapper resource="cn/itsource/domain/ProductMapper.xml" /> 
	</mappers> 
</configuration> 

Properties file: db.properties

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql:///test0303
db.username=root
db.password=admin

Mapping file:

  1. Our mapping file (also called mapper file) is generally in the same package as its corresponding domain entity class;
  2. The name of this mapping file is generally called XxxMapper.xml (Xxx represents the name of the entity class)
For example, the entity class is:
cn.itsource.domain.Product
mapping file name:
cn/itsource/domain/ProductMapper.xml
  1. The name of the namespace is usually the fully qualified name of the interface;
  2. Except for the types supported by MyBatis, all other types are fully qualified
<?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的主要功能就是写sql
	 mapper:根
	 namespace:命令空间 (用来确定唯一)以前这个是可以不加的,现在必需加
     namespace的值:接口的完全限定名
 -->
<mapper namespace="cn.itsource.dao.IProductDao">
	<!-- 
		select :这里面写查询语句
		id:用来确定这条sql语句的唯一
			   以后我们确定唯一,也就是找sql语句 : namespace + id
			 例: cn.itsource.mybatis.day1._1_hello.IProductDao.get
		parameterType : 传入的参数类型  long:大Long  _long:小long (具体的对应请参见文档)
		resultType : 结果类型(第一条数据返回的对象类型)自己的对象一定是完全限定类名
	 -->
	<select id="get" parameterType="long" resultType="cn.itsource.domain.Product">
		select * from product where id = #{id}
	</select>
</mapper> 

Getting started code:

@Override
public Product get(Long id) {
	SqlSession session = null;
	try {
		Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        session = sqlSessionFactory.openSession();
		// 两个参数:mapper的nameSpace+id的路径,和需要的参数
		return session.selectOne(NAME_SPACE+"get", id);
	} catch (Exception e) {
		e.printStackTrace();
		throw new RuntimeException("使用get方法出错:" + e.getMessage());
	} finally {
		if (session != null) {
			session.close();
		}
	}
}

4.4. Other implementations

package cn.itsource.mybatis._01_hello.dao.impl;

import cn.itsource.mybatis._01_hello.dao.IProductDao;
import cn.itsource.mybatis._01_hello.domain.Product;
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 java.io.Reader;
import java.util.List;

/**
 * dao实现
 *
 *    insert:添加,事务控制
 *    delete:删除,事务控制
 *    update:修改,事务控制
 *    selectOne:查询一个
 *    SelectList:查询多个
 */
public class ProductDaoImpl implements IProductDao {
    @Override
    public void save(Product product) {
        SqlSession sqlSession = null;
        try {
            //1 准备配置文件 ok
            //2 创建SqlSessionFactory
            Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            //3 获取sqlSession做操作
            sqlSession = sqlSessionFactory.openSession();
            //表示调用那句sql(namespace+.+id)-拷贝,传入参数,接收得到返回值
            sqlSession.insert("cn.itsource.dao.IProductDao.save",product);
            //提交事物-增删改,数据库存储引擎不能是myIsam,它不支持事务
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    @Override
    public void remove(Long id) {
        SqlSession sqlSession = null;
        try {
            //1 准备配置文件 ok
            //2 创建SqlSessionFactory
            Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
         
            //3 获取sqlSession做操作
            sqlSession = sqlSessionFactory.openSession();
            //表示调用那句sql(namespace+.+id)-拷贝,传入参数,接收得到返回值
             sqlSession.delete("cn.itsource.dao.IProductDao.remove",id);
             //提交事物-增删改,数据库存储引擎不能是myIsam,它不支持事务
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    @Override
    public void update(Product product) {
        SqlSession sqlSession = null;
        try {
            //1 准备配置文件 ok
            //2 创建SqlSessionFactory
            Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
         
            //3 获取sqlSession做操作
            sqlSession = sqlSessionFactory.openSession();
            //表示调用那句sql(namespace+.+id)-拷贝,传入参数,接收得到返回值
            sqlSession.update("cn.itsource.dao.IProductDao.update",product);
            //提交事物-增删改,数据库存储引擎不能是myIsam,它不支持事务
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    @Override
    public Product loadById(Long id) {

        SqlSession sqlSession = null;
        try {
            //1 准备配置文件 ok
            //2 创建SqlSessionFactory
            Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
         
            //3 获取sqlSession做操作
            sqlSession = sqlSessionFactory.openSession();

            //表示调用那句sql(namespace+.+id)-拷贝,传入参数,接收得到返回值
            return  sqlSession
                    .selectOne("cn.itsource.dao.IProductDao.loadById",id);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
        return null;
    }

    @Override
    public List<Product> loadAll() {
        SqlSession sqlSession = null;
        try {
            //1 准备配置文件 ok
            //2 创建SqlSessionFactory
            Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
         
            //3 获取sqlSession做操作
            sqlSession = sqlSessionFactory.openSession();

            //表示调用那句sql(namespace+.+id)-拷贝,传入参数,接收得到返回值
            return  sqlSession
                    .selectList("cn.itsource.dao.IProductDao.loadAll");

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
        return null;
    }
}

package cn.itsource.mybatis._01_hello.dao;

import cn.itsource.mybatis._01_hello.dao.impl.ProductDaoImpl;
import cn.itsource.mybatis._01_hello.domain.Product;
import org.junit.Test;

/**
 * 打印快捷方式:obj.sout
 * 快速省略测试:类里面-右键-goto-junit4-勾上
 */
public class IProductDaoTest {
    IProductDao productDao = new ProductDaoImpl();

    @Test
    public void save() {
        Product product = productDao.loadById(18L);
        product.setId(null);
        product.setProductName("yhptest......");
        productDao.save(product);
    }

    @Test
    public void remove() {
        Product product = productDao.loadById(19L);
        System.out.println(product);
        productDao.remove(19L);
        product = productDao.loadById(19L);
        System.out.println(product);
    }

    @Test
    public void update() {
        Product product = productDao.loadById(22L);
        System.out.println(product);
        product.setProductName("yhptest......edit");
        productDao.update(product);
        product = productDao.loadById(22L);
        System.out.println(product);
    }

    @Test
    public void loadById() {
        //obj.sout
        System.out.println(productDao.loadById(1L));
    }

    @Test
    public void loadAll() {
        for (Product product : productDao.loadAll()) {
            System.out.println(product);
        }
    }
}

4.5. Attention

Configure the constraints in the XML to make it prompt:

Insert picture description here

5.Mybatis tools

5.1. MybatisUtil extraction

5.1.1. Why extract

  1. In fact, every Dao method must obtain SQLSession and close it after use. Operations such as obtaining and closing should be handed over to the tool;

5.1.2. Extraction theoretical analysis

SqlSessionFactoryBuilder:
Builder mode: The object we finally get is very complicated. Use this builder to complete these complex codes for us first. This class can be instantiated, used and discarded. Once you have created the SqlSessionFactory, this class object does not need to exist. Therefore, the best scope of the SqlSessionFactoryBuilder instance is the method scope (that is, the local method variable). You can reuse SqlSessionFactoryBuilder to create multiple SqlSessionFactory instances, but the best way is not to keep it always there to ensure all XML parsing resources, because there are more important things to do;

SqlSessionFactory:
Once created, SqlSessionFactory should exist during the execution of your application. There is no reason to process or recreate it. The best practice for using SqlSessionFactory is not to create it multiple times during the running of the application. Such operations would be considered very bad. Therefore, the best scope of SqlSessionFactory is the scope of application. There are many ways to do it, the easiest is to use singleton mode or static singleton mode. However, neither of these methods are considered best practices. In this case, you can consider dependency injection containers, such as Google Guice or Spring. Such a framework allows you to create support programs to manage the life cycle of a singleton SqlSessionFactory;

SqlSession
Each thread should have its own SqlSession instance. Instances of SqlSession cannot be shared, and it is also thread-unsafe. So the best scope is the request or method scope. Never put a reference to a SqlSession instance in a static field or even an instance field of a class. Never put the reference of the SqlSession instance in any type of management scope, such as the HttpSession in the Serlvet architecture. If you are currently using any web framework, consider that SqlSession is placed in a similar scope to the HTTP request object. In other words, based on the received HTTP request, you can open a SqlSession, and then return a response, you can close it. Close Session is very important;

5.1.3. Extraction

Insert picture description here

5.2. Use tools to complete CRUD

5.2.1. Query a piece of data

sql
code

5.2.2. Query all data

sql
code

5.2.3. Add a piece of data

Note: When adding, you must remember to commit the transaction (configuration transaction, table structure support transaction)
sql
code

5.2.4. Modify a piece of data

sql
code

5.2.5. Delete a piece of data

sql
code

6.SQL Mapper Mapper

6.1. Introduction

Introduction: When operating the database through Mybatis before, in addition to writing the interface, you also need to write the implementation class. MyBatis is based on a dynamic proxy mechanism, so that we no longer need to write Dao implementations, but we must follow certain specifications:

  1. Traditional Dao interface, now the name uniformly ends with Mapper: For example: IUserDao --> UserMapper
  2. And our mapper configuration file should be in the same package as the mapper:
    (1) Package: cn.itsource.mapper (UserMapper interface and UserMapper.xml)
  3. The namespace in UserMapper.xml directly writes the fully qualified name of the UserMapper interface;
Insert picture description here

Mapping file:

<mapper namespace="cn.itsource.mybatis.mapper.UserMapper">
	<select id="接口的方法名" parameterType="long" resultType="User">
Select * from t_user where id = #{id}
</select>
</mapper>

6.2. Mapper implementation steps

  1. According to the requirements, create the Mapper interface related to the model, for example: UserMapper;
  2. Write the mapping file in the same package, for example: UserMapper.xml;
    (1) The namespace of the Mapper mapping file must be consistent with the "fully qualified name" of the interface;
    (2) The id of the sql tag needs to be defined with the "interface method" The same name
  3. Configure (or register) the Mapper mapping file in the Mybatis core configuration file;
  4. Test;
    friendly reminder: It is best not to use method overloading in the mapper interface, because the id of the sql tag is the method name, and writing overloaded methods is prone to problems;

6.3. Implementation

Interface implementation method one (traditional):

Insert picture description here

Interface implementation method two (mapper):

Insert picture description here

6.4. Adding is to return the self-increasing ID

  1. Generally speaking, database tables have a primary key id and are self-growing. When adding data, if you do not add an id, the database will automatically obtain the current maximum id, and this maximum id will be incremented by one as the id value of the data to be added;
  2. Sometimes we need to get this self-incremented id after executing the insert submission. Because it may be used as the basis for the next query, or the certificate of the next foreign key inserted;

6.4.1. Method 1:

XxxMapper写法:
public interface ProductMapper {
	//自增长ID
	void insert1(Product product);
}
XxxMapper.xml写法:
<!-- 插入数据并返回自增ID
有自增ID功能数据库可以采用useGeneratedKeys="true"开启判断是否是自增ID
keyProperty="id"  指定插入数据后自增ID返回时赋值给实体类的那个属性(这里是id属性)
-->
<!-- void insert1(Product product) -->
<insert id="insert1"  useGeneratedKeys="true" keyProperty="id">
	insert into product(productName) values(#{productName})
</insert>
测试:
@Test
public void testInsert(){
	SqlSession session = MybatisUtil.getSqlSession();
	ProductMapper mapper = session.getMapper(ProductMapper.class);
		
	Product product = new Product();
	product.setProductName("绿茶111");
	System.out.println("====执行前===="+product.getId());
		
	mapper.insert1(product);
	System.out.println("====执行后===="+product.getId());
	session.commit();
	session.close();
}

6.4.2. Method two:

1. Obtain the self-incrementing primary key of the newly inserted record through the mysql function: LAST_INSERT_ID(), but this function is called after insert.

XxxMapper写法:
public interface ProductMapper {
	//自增长ID
	void insert2(Product product);
}
XxxMapper.xml写法:
<!-- void insert2(Product product) -->
<insert id="insert2">
	<!-- 将插入数据的主键返回,返回到product对象中
	 	SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用于自增主键
	 	keyProperty:将查询到主键值设置到parameterType指定的对象的那个
	 	resultType:指定SELECT LAST_INSERT_ID()的结果类型selectKey中resultType属性指定期望主键的返回的数据类型,
	 	keyProperty属性指定实体类对象接收该主键的字段名
	 	order属性指定执行查询主键值SQL语句是在插入语句执行之前还是之后(可取值:after和before)
         注:mysql用after,oracle用before
	 -->
	<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
	 	SELECT LAST_INSERT_ID()	
	 </selectKey>
	insert into product(productName) values(#{productName})
</insert>
测试:
@Test
public void testInsert(){
	SqlSession session = MybatisUtil.getSqlSession();
	ProductMapper mapper = session.getMapper(ProductMapper.class);
		
	Product product = new Product();
	product.setProductName("绿茶111222");
	System.out.println("====执行前===="+product.getId());
		
	mapper.insert2(product);
	System.out.println("====执行后===="+product.getId());
	session.commit();
	session.close();
}

7. Mybtis usage details

7.1. View MyBatis running log

7.1.1. Why do you need a log

Many times when using MyBatis, we need to print out the log to help us analyze and troubleshoot. Especially at the learning stage, everyone is required to open the MyBatis log;

7.1.2. Common log framework

  1. System.out.print("xxxx")
  2. Write a log framework dblLog.jar(yhptest)
    Log log = LogFactory.getLog(this.class)
    log.error/Info/warn...
  3. Write a log framework dzlLog.jar(ttttt)
    Log log = Factory.getLog(this.class)
    log.error/Info/warn...
  4. Defining standards
    (1) The newly written log framework is made in accordance with the log standard;
    (2) The previous log framework uses an adapter for adaptation;
  5. Standard: slf4j (standard) - commons.logging, log4j (achieve)

7.1.3.Log4j achieve diary

  1. Log4j is mainly used for the output of log information. The information can be divided into levels (serious fatal, error error, warning warn, debugging, information info) in different ways (console, file, database) and format output;
  2. The implementation steps are as follows:
    (1) Import the log4j jar package (3);
    (2) Add log4j.properties under the classpath [name cannot be changed];
    (3) Log level: debug (for debugging), info, warn, error (used at runtime)
    (4) In the log we can see the executed SQL statement, we can see the parameters we passed
  3. Log4j mainly consists of the following three components:
    (1) Logger (level Logger): responsible for message output, providing various output methods at different levels;
    (2) Appender (appender): responsible for controlling the way of message output, For example, output to the console, file output, etc.;
    (3) Layout (formatter, Layout): responsible for controlling the output format of the message;
  4. To open the log in the project, you create a log4j.properties [name do not modify] file in the root directory of the resource file, and copy the following code into it:
#日志器logger #輸出器appender #布局器layout
#1.控制台输出
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=info,myconsole
#指定输出器
#log4j.appender.myconsole=org.apache.log4j.ConsoleAppender
#指定布局器
#log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout

#2.文件输出.txt
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=error,myfile
#指定输出器
#log4j.appender.myfile=org.apache.log4j.FileAppender
#log4j.appender.myfile.File=E:\\log4j.txt
#指定布局器(普通布局表示文本输出)
#log4j.appender.myfile.layout=org.apache.log4j.SimpleLayout

#3.文件输出.html
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=error,myhtml
#指定输出器
#log4j.appender.myhtml=org.apache.log4j.FileAppender
#log4j.appender.myhtml.File=D:\\log4j.html
#指定布局器(网页布局)
#log4j.appender.myhtml.layout=org.apache.log4j.HTMLLayout


#4.控制台输出+文件输出.txt
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=error,con,file
#指定输出器
#log4j.appender.con=org.apache.log4j.ConsoleAppender
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=D\:\\log4j.txt
#指定布局器(网页布局)
#log4j.appender.con.layout=org.apache.log4j.SimpleLayout
#log4j.appender.file.layout=org.apache.log4j.SimpleLayout


#5.控制台输出+自定义布局
log4j.rootLogger=DEBUG,my
#指定输出器
log4j.appender.my=org.apache.log4j.ConsoleAppender
#指定布局器(自定义布局)
#指定布局为自定义布局
log4j.appender.my.layout=org.apache.log4j.PatternLayout
#指定在自定义布局的格式,%d -- 表示当前系统时间,%t -- 执行该业务的线程名称,%p -- 日记器的级别,-5 -- 5表示输出字符的个数,符号表示右对齐
#%c -- 表示指定业务所在的类的完全限定名(包名.类名),%m -- 输出额外信息,%n -- 表示换行
log4j.appender.my.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#设置package(可以是自定义的包也可以是api的包)输出级别
log4j.logger.org.springframework=info
log4j.logger.cn.itsource=debug

Note: The red part above is what we need to modify. It roughly indicates the current log of the files below which will be printed; if the configuration is successful, then the corresponding log can be seen when MyBatis runs the operation data;

7.2. Using aliases in MyBatis

  1. Alias ​​is to obtain a small name for the class, you can use the small name to replace the real name in the future. In Mybatis, the name of the entity class is simplified to facilitate development. The alias is divided into built-in aliases and custom aliases;

7.2.1. Built-in aliases

Insert picture description here

7.2.2. Custom alias

<typeAliases>
		<!-- 单个配置:测试时使用 -->
		<typeAlias type="cn.itsource.domain.Dept" alias="Dept" />
		<!-- 包的配置:项目中使用,添加了包之后,类名或类名首字母小写就是别名 -->
		<package name="cn.itsource.domain" />
</typeAliases>

7.3. The difference between # and $

7.3.1.#{OGNL expression}

MyBatis will replace this expression with? (Placeholder) as a sql parameter: recommended. For example, the value of name is:
define SQL: select * from t_user where name = #(name)
final SQL: select * from t_user where name =?

7.3.2. ${OGNL expression}

  1. MyBatis will replace the value of this expression into sql as a component of sql. Splice the obtained value directly into SQL;
  2. If ${OGNL} is used in sql, and the type of the parameter is (integer, string...), then the OGNL expression can be written in any form;

7.3.3. Application scenarios of ${OGNL} expressions

  1. Cannot be used for login, there will be SQL injection. For
    example, the login function can be artificially made successfully when entering the name:
User user=new User();
user.setName("\"admin\" or \"1=1\" ");
user.setPassword("\"admin\"  ");
     定义SQL: select id,name,password from t_user where name = ${name} and password=${password}
     最终SQL: select id,name,password from t_user where name="test" or "1=1" and password="test"  出现sql注入
  1. Used in order by + limit scenarios
Insert picture description here

Note: Except for the use of $ to splice the sql structure (which is direct splicing of sql), all others use #, because # will be replaced with ?, and finally the parameters will be set through PreparedStament, there will be no SQL injection problems;

8. Course summary

8.1. Key points

  1. Getting started with Mybatis
  2. CRUD operation of Mybatis
  3. Mybatis usage details

8.2. Difficulties

  1. Mybatis usage details
  2. Positioning error

8.3. How to master

  1. Practice hard
  2. Learn to read the instruction manual

8.4. Troubleshooting skills (techniques)

9. Frequently Asked Questions

  1. No driver package imported into the database;
  2. Many of the XML in XML are strings, be careful and don’t make mistakes;
  3. The fully qualified name in the mapping file may be wrong;
  4. Cannot find the corresponding Statement (sql statement)
    (1) Find the SQL statement wrong;
    (2) Did not find the corresponding mapping file in the core XML;
  5. When we call Statement (sql statement), we often forget to pass parameters;
  6. After the execution is successful, the database does not reflect, it is very likely that the transaction has not been committed;
  7. Maybe we forgot to write the execution code;
  8. Errors must be printed out (there is no effect when executed, but no error is reported);
  9. Even if a statement is not used in Mapper, its error may affect other correct statements;
  10. The mistakes of the framework are often found from the back to the front;
  11. Many students did not use aliases, but he kept using them;
  12. Character encoding: useUnicode=true&characterEncoding=UTF-8

10. Practice after class

  1. Class code 1-2 times;

11. Interview questions

  1. Contact and difference between Mybatis and Jdbc; (expected to be completed in 10 minutes)
  2. Mybatis and Jpa implementation framework Hibernate distinction and connection; (expected to be completed in 10 minutes)

12. Extended knowledge or extracurricular reading recommendation (optional)

12.1. Expanding knowledge

Mybatis and Hibernate difference?

  1. Hibernate
    (1) Advantages: For simple CRUD, no SQL statements can be written, and the code is portable (different databases can be replaced);
    (2) Disadvantages:
    ①Hibernate is not flexible enough, and support for complex SQL is weak;
    ②HQL black box operation, tuning High complexity;
    ③Not suitable for the high-performance requirements of large-scale Internet projects;
  2. Mybatis
    (1) Advantages: Highly flexible, self-operating SQL, convenient for optimization. Low learning threshold, easy to maintain and develop;
    (2) Disadvantages: Since the SQL statements of each database are different, the code is not portable;

12.2. Extracurricular reading