Code warehouse

MyCode_JavaWeb_Framework


1. Overview of Mybatis

1.1 Object/Relational Database Mapping (ORM)

  • ORM Framework Introduction
N/A ORM Object/Relation Mapping N/A ORM enables the Mapping of object-oriented programming languages to relational databases. When the ORM framework is mapped, programmers can take advantage of both the simplicity and ease of use of object-oriented programming languages and the technical benefits of relational databases. - ORM wraps relational databases as an object-oriented model. - ORM framework is an intermediate solution when the development of object-oriented design language and relational database is not synchronized. - With the ORM framework, applications no longer access the underlying database directly, but operate on persistent objects in an object-oriented manner, and the ORM framework translates these object-oriented operations into the underlying SQL operations. - The ORM framework converts the operation of saving, modifying, and deleting persistent objects into the operation of the databaseCopy the code
  • The ORM classification
The name of the Characteristics of the describe
Hibernate Fully automatic You don’t need to write SQL
mybatis semi-automatic Manual, automatic integration, support simple mapping, complex relationship to write SQL
Spring JDBC Pure manual All SQL needs to write their own, a standard process

1.2 introduction of Mybatis

- MyBatis is an excellent semi-automatic lightweight persistent layer framework based on ORM. It supports customized SQL, stored procedures, and advanced mapping, encapsulating the process of manipulating a DATABASE in JDBC - MyBatis avoids almost all JDBC code and manually setting parameters and fetching result sets MyBatis can use simple XML or annotations to configure and map native types, interfaces, and Java poJOs (Plain Old Java Objects, Plain old Java objects) for records in the database - Mybatis is configured with various statements (Statement, preparedStatemnt, CallableStatement) that will be executed either through XML or annotations. In addition, Java objects and SQL in statement are mapped to generate the final SQL statement. Finally, Mybatis framework executes SQL, maps the result to Java objects and returns itCopy the code

1.3 Development history of MyBatis

IBatis is a java-based persistence layer framework, which includes SQL Maps and abatis. IBatis is a java-based persistence layer frameworkData Access Objects(DAO)- In June 2010, the open source project iBatis was migrated from Apache Software Foundation to Google Code. As the development team moved to Google Code, Ibatis3.x officially renamed to Mybatis - Code migrated to Github in November 2013Copy the code

1.4 advantages of MyBatis

- Mybatis is a semi-automated persistence layer framework, which opens to developers that core SQL still needs to be optimized by itself, SQL and Java coding are separated, functional boundaries are clear, one focuses on business, one focuses on data - so that developers only need to pay attention to SQL itself. You don't have to deal with the tedious JDBC process code (registering drivers, creating connections, creating statements, manually setting parameters, retrieving result sets, etc.)Copy the code

1.5 MyBatis source download and overview

  • Official website: www.mybatis.org/mybatis-3/
  • Download source address: github.com/mybatis/myb…
  • File Package Description
Jar: Mybatis core package mybatis-xxx. PDF: Mybatis user manualCopy the code

1.6 [difference] Mybatis & Hibernate

The difference between Mybatis Hibernate
In essence semi-automatic Fully automatic
security SQL injection problems exist precompiled
Logging system Square root
portability Square root
flexibility Square root

(1) Essentially

Hibernate is automatic: Hibernate can achieve the operation of the database through the object relationship model, has a complete JavaBean object and database mapping structure, so as to automatically generate SQL statements. MyBatis only has basic field mapping, object data and actual object relationships still need to be implemented and managed through custom SQL statements - Hibernate costs significantly less than MyBatis when switching database typesCopy the code

(2) Log system: Hibernate >> MyBatis

- Hibernate has a complete logging system (such as: SQL record, relationship exception, optimization warning, cache alert, dirty data warning, etc.) - MyBatis in addition to the basic recording function, the function is weakCopy the code

(3) Portability: Hibernate >> MyBatis

Hibernate through its powerful mapping structure and HQL language, greatly reduce the object and database (Oracle, MySQL, etc.) coupling - MyBatis due to the need for handwritten SQL, so the coupling with the database directly depends on the programmer to write SQL method, If SQL is not general-purpose and uses many SQL statements with certain fixed database features, portability can be reduced and costs can be highCopy the code

4) Flexibility: MyBatis >> Hibernate

- SQL optimization, MyBatis is directly written into the original SQL XML, SQL execution performance can be strictly controlled, high flexibility, very suitable for the relational data model is not high requirements for software development - SQL optimization, Hibernate SQL is a lot of automatic generation, No direct maintenance - HQL is also limited in some complex business requirements - Hibernate supports native SQL, but it is different from ORM in development mode and requires a change of thinking, so it is not very convenient to useCopy the code

(5) Security

- Hibernate is precompiled - MyBatis may have SQL injection problemsCopy the code

2. Introduction of Mybatis

2.1 Native JDBC writing method

public static void main(String[] args) {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
  try {
    // Load the database driver
    Class.forName("com.mysql.jdbc.Driver");
    
    // Get the database link from the driver management class
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis? characterEncoding=utf-8"."root"."root");
 
    // Define SQL statements? Represents a placeholder
    String sql = "select * from user where username = ?";

    // Get the preprocessed statement
    preparedStatement = connection.prepareStatement(sql);

    The first parameter is the sequence number (starting from 1) of the parameter in the SQL statement, and the second parameter is the value of the parameter
    preparedStatement.setString(1."tom");

    // Issue SQL to the database to execute the query and query the result set
    resultSet = preparedStatement.executeQuery();

    // Iterate over the query result set
    while (resultSet.next()) {
		int id = resultSet.getInt("id");
		String username = resultSet.getString("username");
		/ / encapsulates the Useruser.setId(id); user.setUsername(username); } System.out.println(user); }}catch (Exception e) {
	e.printStackTrace();
 } finally {
	// Release resources
	if(resultSet ! =null) {
		try {
			resultSet.close();
		} catch(SQLException e) { e.printStackTrace(); }}if(preparedStatement ! =null) {
		try {
			preparedStatement.close();
		} catch(SQLException e) { e.printStackTrace(); }}}Copy the code

2.2 Mybatis solves JDBC programming problems

  • The problems with native JDBC development are as follows
(1- Solution: Use the database connection pool to initialize connection resources, configure the data connection pool in sqlmapconfig. XML, and use the connection pool to manage database connections (2Sql statement is hard coded in the code, resulting in code is not easy to maintain, the actual application of Sql changes may be large, Sql changes need to change the Java code - solution: Sql statement configuration/extraction in xxxxmapper.xml file, so as to separate from the Java code (3Hard coding occurs when you use preparedStatement to transmit parameters to possession bit symbols, because SQL statements may have more or less WHERE conditions. Modifying SQL requires modifying code, and the system is not easy to maintain. Mybatis automatically maps Java objects to SQL statements. ParameterType specifies input parameter types for SQL statements. Mybatis automatically maps Java objects to SQL statements.4) There is hard coding for result set parsing (query column name), SQL changes lead to parsing code changes, the system is not easy to maintain, if the database records can be encapsulated as POJO object parsing is more convenient - Cause: SQL changes cause parsing code changes, and need to be traversed before parsing - Solve: Use reflection, introspection and other low-level technologies to automatically map attributes and fields of entities and tables (Mybatis will automatically map SQL execution results to Java objects and define output result types through resultType in Statement)Copy the code

2.3 Custom framework Design

(1) User: provide core configuration files

Sqlmapconfig. XML: stores database configuration information. Mapper. XML: stores configuration file information of SQL statements (including SQL statements, parameter types, and return value types)Copy the code

(2) Framework side: the essence is to encapsulate JDBC code

(1Read configuration file - Based on the path of the configuration file, load the configuration file as a byte input stream and store it in memory (2JavaBean (container object) : javaBean (container object) : javaBean (container object) : javaBean (container object) : javaBean XML (including basic database information and Map< unique identifier, Mapper>) - Unique identifier: Namespace +"."+ id-mappedStatement Mapping configuration class: Stores contents parsed by mapper. XML (including SQL statements, Statement types, input parameter Java types, and output parameter Java types) (3Create sqlSessionFactoryBuilder classsqlSessionFactory build(inputSteam in): - Use dom4J to parse the Configuration file and encapsulate the parsed content into the Configuration and MappedStatement container objects - create SqlSessionFactory object, (4) Create SqlSessionFactory interface and implement defaultsQlsessionFactory-OpenSession () method to generate sqlSession (5) Create SqlSession interface and implement DefaultSession class, define CRUD operations on the database (encapsulate JDBC to complete the query operation on the database table)selectList(String statementId,Object param): Query allselectOne(String statementId,Object param): query a single update () the delete () to (6) create Executor interface and implementation classes SimpleExecutor implementation class query (Configuration, MapperStatement, Object... Params) : The design patterns involved in executing JDBC code: Builder design pattern, factory pattern, proxy patternCopy the code

2.4 Custom framework implementation

Using the

Step 0: Pom.xml dependency package
 <! -- Introducing custom persistence layer framework dependencies -->
<dependencies>
    <dependency>
        <groupId>com.loto.mybatis</groupId>
        <artifactId>mybatis2-custom</artifactId>
        <version>1.0 the SNAPSHOT</version>
    </dependency>

    <! A toolkit for simplifying bean code
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
    </dependency>
</dependencies>
Copy the code
Step 1: Create a configuration file sqlmapconfig.xml
<configuration>
    <! -- Database configuration information -->
    <dataSource>
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="JDBC: mysql: / / / JavaWeb_7. 1 _mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </dataSource>

    <! Where mapper.xml is stored -->
    <mapper resource="UserMapper.xml"/>
</configuration>
Copy the code
Step 2: usermapper.xml
<mapper namespace="com.loto.mybatis.dao.IUserDao">
    <! StatementId: namespace.id-->

    <select id="findByCondition" resultType="com.loto.mybatis.pojo.User" parameterType="com.loto.mybatis.pojo.User">
        select * from user where id = #{id} and username = #{username}
    </select>

    <select id="findAll" resultType="com.loto.mybatis.pojo.User">
        select * from user
    </select>
</mapper>
Copy the code
Step 3: User.java entity
package com.loto.mybatis.pojo;

import lombok.Data;

@Data
public class User {
	private Integer id;
	private String username;
	private String password;
}

Copy the code
Step 4: Test the class
package com.loto.mybatis.test;

import com.loto.mybatis.dao.IUserDao;
import com.loto.mybatis.io.Resources;
import com.loto.mybatis.pojo.User;
import com.loto.mybatis.sqlsession.SqlSession;
import com.loto.mybatis.sqlsession.SqlSessionFactory;
import com.loto.mybatis.sqlsession.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class Test_MybatisCustom {
	/** * query all */
	@Test
	public void test_findAll(a) throws Exception {
		InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml");
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
		SqlSession sqlSession = sqlSessionFactory.openSession();

		List<User> users = sqlSession.selectList("com.loto.mybatis.dao.IUserDao.findAll");
		for(User user1 : users) { System.out.println(user1); }}/** ** select */
	@Test
	public void test_findByCondition(a) throws Exception {
		InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml");
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
		SqlSession sqlSession = sqlSessionFactory.openSession();

		/ / call
		User user = new User();
		user.setId(1);
		user.setUsername("TD");

		// Unique identifier of SQL statementId: namespace.id
		User user2 = sqlSession.selectOne("com.loto.mybatis.dao.IUserDao.findByCondition", user);
		System.out.println(user2);
	}

	/** * implements the method */ through the Dao
	@Test
	public void test_getMapper(a) throws Exception {
		InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml");
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
		SqlSession sqlSession = sqlSessionFactory.openSession();

		IUserDao userDao = sqlSession.getMapper(IUserDao.class);
		List<User> all = userDao.findAll();
		for(User user1 : all) { System.out.println(user1); }}}Copy the code

Frame side

Step 0: Pom.xml dependency package
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>

    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <! -- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.1</version>
    </dependency>

    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>

    <dependency>
        <groupId>jaxen</groupId>
        <artifactId>jaxen</artifactId>
        <version>1.1.6</version>
    </dependency>
    
    <! A toolkit for simplifying bean code
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
    </dependency>
</dependencies>
Copy the code
Step 1: Configuration.java
package com.loto.mybatis.pojo;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

public class Configuration {
	private DataSource dataSource;

	/** * key: statementid 

* value: encapsulated mappedStatement object */

Map<String, MappedStatement> mappedStatementMap = new HashMap<>(); public DataSource getDataSource(a) { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public Map<String, MappedStatement> getMappedStatementMap(a) { return mappedStatementMap; } public void setMappedStatementMap(Map<String, MappedStatement> mappedStatementMap) { this.mappedStatementMap = mappedStatementMap; }}Copy the code
Step 2: mappedStatement.java
package com.loto.mybatis.pojo;

import lombok.Data;

@Data
public class MappedStatement {
	/** * ID */
	private String id;

	/** * Return value type */
	private String resultType;

	/** * Parameter value type */
	private String paramterType;

	/** * SQL statement */
	private String sql;
}
Copy the code
Step 3: Resources.java
package com.loto.mybatis.io;

import java.io.InputStream;

public class Resources {
	/** * Load the configuration file into a byte input stream and store it in memory */
	public static InputStream getResourceAsSteam(String path) {
		returnResources.class.getClassLoader().getResourceAsStream(path); }}Copy the code
Step 4: the SqlSessionFactoryBuilder is Java
package com.loto.mybatis.sqlsession;

import com.loto.mybatis.config.XMLConfigBuilder;
import com.loto.mybatis.pojo.Configuration;
import org.dom4j.DocumentException;

import java.beans.PropertyVetoException;
import java.io.InputStream;

public class SqlSessionFactoryBuilder {
	public SqlSessionFactory build(InputStream in) throws DocumentException, PropertyVetoException {
		// First: use dom4j to parse the Configuration file and encapsulate the parsed content in Configuration
		XMLConfigBuilder xmlConfigBuilder = new XMLConfigBuilder();
		Configuration configuration = xmlConfigBuilder.parseConfig(in);

		// Create sqlSessionFactory: factory class: produce sqlSession: session object
		DefaultSqlSessionFactory defaultSqlSessionFactory = new DefaultSqlSessionFactory(configuration);

		returndefaultSqlSessionFactory; }}Copy the code
Step 5: xmlConfigBuilder.java
package com.loto.mybatis.config;

import com.loto.mybatis.io.Resources;
import com.loto.mybatis.pojo.Configuration;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

public class XMLConfigBuilder {
	private Configuration configuration;

	public XMLConfigBuilder(a) {
		this.configuration = new Configuration();
	}

	/** * Parse the Configuration file using dom4j and encapsulate it as Configuration */
	public Configuration parseConfig(InputStream inputStream) throws DocumentException, PropertyVetoException {
		Document document = new SAXReader().read(inputStream);

		//<configuration>
		Element rootElement = document.getRootElement();
		List<Element> list = rootElement.selectNodes("//property");
		Properties properties = new Properties();
		for (Element element : list) {
			String name = element.attributeValue("name");
			String value = element.attributeValue("value");
			properties.setProperty(name, value);
		}

		ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
		comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
		comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
		comboPooledDataSource.setUser(properties.getProperty("username"));
		comboPooledDataSource.setPassword(properties.getProperty("password"));

		configuration.setDataSource(comboPooledDataSource);

		// mapper. XML parsing: take the path -- byte input stream -- dom4j to parse
		List<Element> mapperList = rootElement.selectNodes("//mapper");
		for (Element element : mapperList) {
			String mapperPath = element.attributeValue("resource");
			InputStream resourceAsSteam = Resources.getResourceAsSteam(mapperPath);
			XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration);
			xmlMapperBuilder.parse(resourceAsSteam);
		}

		returnconfiguration; }}Copy the code
Step 6: xmlMapperBuilder.java
package com.loto.mybatis.config;

import com.loto.mybatis.pojo.Configuration;
import com.loto.mybatis.pojo.MappedStatement;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.List;

public class XMLMapperBuilder {
	private Configuration configuration;

	public XMLMapperBuilder(Configuration configuration) {
		this.configuration = configuration;
	}

	public void parse(InputStream inputStream) throws DocumentException {
		Document document = new SAXReader().read(inputStream);
		Element rootElement = document.getRootElement();
		String namespace = rootElement.attributeValue("namespace");

		List<Element> list = rootElement.selectNodes("//select");
		for (Element element : list) {
			String id = element.attributeValue("id");
			String resultType = element.attributeValue("resultType");
			String parameterType = element.attributeValue("parameterType");
			String sqlText = element.getTextTrim();

			MappedStatement mappedStatement = new MappedStatement();
			mappedStatement.setId(id);
			mappedStatement.setResultType(resultType);
			mappedStatement.setParamterType(parameterType);
			mappedStatement.setSql(sqlText);
			String key = namespace + "."+ id; configuration.getMappedStatementMap().put(key, mappedStatement); }}}Copy the code
See code repository for other files

3, Mybatis API

3.1 SqlSessionFactoryBuilder

Commonly used API:SqlSessionFactory build(InputStream inputStream)Build a SqlSessionFactory object InputStream resourceAsStream by loading the mybatis core file as an InputStream= Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(resourceAsStream); Resources utility class - in the org.apache.ibatis. IO package - What it does: The Resources class helps you load resource files from the classpath, file system, or a Web URLCopy the code

SqlSessionFactory (SqlSession factory object)

  • SqlSessionFactory has several methods to create an INSTANCE of SqlSession. The following two methods are commonly used
methods explain
openSession() A transaction is enabled by default and will not commit automatically (the transaction must be committed manually to persist the updated operation data to the database).
openSession(boolean autoCommit) The parameter is whether to commit automatically. If this parameter is set to True, the transaction does not need to be committed manually

3.3 Session (Session Object)

  • The method by which statements are executed
<T> T selectOne(String statement, Object parameter) 
<E> List<E> selectList(String statement, Object parameter)
    
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)

Copy the code
  • Methods for manipulating transactions
void commit(a) 
void rollback(a)
Copy the code


Author: LAN Tian _Loto

[Code Hosting platform]

Github

[If you have any questions, please communicate through the following methods]

① Reply in the comment section ② Send an email to [email protected]

The copyright of this article belongs to the author and this website, welcome to reprint, but without the consent of the author must retain this statement, and give the original text link in the obvious position of the article page, thank you for your cooperation.