mybatis must know

1、SqlSessionFactory

2、SqlSession

3. Mapper XML file

4. Dynamic SQL

5. Common API

6. Integrate spring

6.1、SqlSessionFactoryBean

6.2、SqlSessionTemplate

 

Frontiers: What is mybatis and why do you need her?

MyBatis is an excellent persistence layer framework that supports custom SQL, stored procedures and advanced mapping.

MyBatis avoids almost all JDBC code and manually setting parameters and getting result sets.

MyBatis can use simple XML or annotations for configuration and native Map to map interfaces and Java POJOs (Plain Old Java Objects, ordinary Java objects) into records in the database.

Advantages: Simpler than native jdbc, write a lot less general code. Simpler, more intuitive and more operable than similar hibernate.

 -------------------------------------------------------------------------------------------------------------------------

1、SqlSessionFactory

To use MyBatis, just put the  mybatis-xxxjar  files on the classpath.

ps: If you use Maven to build the project, you need to put the following dependency code in the pom.xml file. The corresponding version can be found in the http://www.mvnrepository.com/maven  central repository, or your own private server.

 

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

 

Every MyBatis-based application is centered on an instance of SqlSessionFactory. In fact, it is a factory for session management.

An instance of SqlSessionFactory can be obtained through SqlSessionFactoryBuilder, and SqlSessionFactoryBuilder can construct an instance of SqlSessionFactory from an XML configuration file or an instance of a pre-customized Configuration.

 

public SqlSessionFactory SqlSessionFactory(){
		DataSource dataSource;//Database connection pool, you can use a third party
		TransactionFactory transactionFactory = new JdbcTransactionFactory();//Things, use the default. You can also cooperate with spring and use spring's own
		Environment environment = new Environment("development", transactionFactory, dataSource);//Environment configuration is development or production
		
		Configuration configuration = new Configuration(environment);//Configuration Center
		//configuration.addMappers("conge.wang.sqlmappers");//Load mappers xml package, and scan the xml configuration under conge.wang.sqlmappers
		//configuration.addMapper(TestSqlMapper.class);//Or load mappers class. However, it is not recommended to use
		
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);//从SqlSessionFactoryBuilder构建
		
		return sqlSessionFactory;
	}
 important point:

 

(1), SqlSessionFactoryBuilder This class can be instantiated, used and discarded. Once the SqlSessionFactory is created, it is no longer needed. So the best scope for a SqlSessionFactoryBuilder instance is method scope ( ie local method variables ). You can reuse the SqlSessionFactoryBuilder to create multiple SqlSessionFactory instances, but it's best not to keep it around to keep all XML parsing resources open to more important things.

 

(2) Once the SqlSessionFactory is created, it should always exist during the runtime of the application, and there is no reason to clear or rebuild it. The best practice for using SqlSessionFactory is not to recreate it multiple times while the application is running, rebuilding the SqlSessionFactory multiple times is considered a "bad smell" of code. So the best scope for SqlSessionFactory is application scope. There are many ways to do it, the easiest is to use the singleton pattern or the static singleton pattern.

 

 

2、SqlSession

SqlSession can be understood as a jdbc Connection.

Each thread should have its own instance of SqlSession. Instances of SqlSession are not thread-safe and therefore cannot be shared, so their optimal scope is request or method scope.

Never place a reference to a SqlSession instance in the static field of a class, not even an instance variable of a class.

也绝不能将 SqlSession 实例的引用放在任何类型的管理范围中,比如 Serlvet 架构中的 HttpSession。

那么也就是说,每次操作时,获取新的SqlSession,并且确保完成数据库操作之后,确保关闭,例如:

 

SqlSession session = sqlSessionFactory.openSession();
try {
  // 业务处理
} finally {
  session.close();
}

 

注意点:

(1)、一定确保SqlSession是线程安全使用

(2)、一定确保使用完成,或者异常时,关闭SqlSession

 

 

3、Mapper XML 文件

MyBatis的核心就在Mapper XML文件的配置,大显身手的地方。

SQL 映射文件有很少的几个顶级元素,

 

resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。

sql – 可被其他语句引用的可重用语句块。

insert – 映射插入语句

update – 映射更新语句

delete – 映射删除语句

 

select – 映射查询语句

 

(0)、先建张表,以备使用,mysql数据库

CREATE TABLE `t_test` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(50) NOT NULL DEFAULT '0',
	`num` INT(11) NOT NULL DEFAULT '0',
	`create_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1
;

 
定义下面的这些的SQL语句之前,别忘了命名空间

 

<?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="t_test">

...//SQL语句配置
</mapper >
 

 

 

(1)、即预定义一些SQL语句,其他SQL配置可以直接引用,省去很多重复编码

<sql id="baseResult">
     id,name,num,create_ts
</sql>

上面定义了t_test 表的所有字段 ,也可以定义一些复杂的通用的SQL代码,但最好一目了然,太复杂不利于维护,二次开发。这也正是魅力所在。

 

(2)、resultMap ,定义SQL表字段对java pojo的映射,可以理解为ORM,对象--表对应

<resultMap id="baseMap" type="pojo.TTest">
	<id column="id"              property="id" />
	<result column="name" 	     property="name" />
	<result column="balance"     property="num" />
	<result column="create_ts"   property="createTs" />
</resultMap>

Although the objects of tables and POJOs are mapped, not all fields are mapped, and it is not necessary to map each table. The fields after the join of multiple tables can also be mapped to a POJO. In a word, flexible use. 

 

(3), select, query statement.

 

<select id="query" parameterType="map" resultMap="baseMap">
	SELECT <include refid="baseResult"/>
		FROM t_test
        WHERE id = #{id}
</select>
 important point:

 

a), id is a unique identifier in the namespace that can be used to refer to this statement.

b), parameterType will pass in the fully qualified name or alias of the parameter class of this statement. This attribute is optional, because MyBatis can infer the parameters of the specific incoming statement through TypeHandler, and the default value is unset.

         In fact, as a parameterType, there are only three types of parameters, 1. Direct data of a basic type 2. A parameter of a java bean, including multiple basic types 3. Map type

c) Named reference to resultMap outside resultMap. The mapping of result sets is the most powerful feature of MyBatis. With a good understanding of it, many complex mapping situations can be easily solved. Use resultMap or resultType, but not both.

d), resultType java class, which contains multiple basic types, like resultMap, used to map the result set 

 There are some other attributes, you can check it when you use it.

 

#{id} is a parameter that receives an id, just like PreparedStatement preprocessed SQL statement, placeholder.

 

(4) insert, update and delete are basically similar

insert statement, selectKey uses the primary key self-growth feature that comes with Mysql 

 

<insert id="insert" parameterType="pojo.TTest">
  insert into t_test(id,name,num)
  values (#{id},#{name},#{num})

        <selectKey keyProperty="id" resultType="java.lang.Long">
		  SELECT LAST_INSERT_ID() AS ID
	</selectKey>
</insert>
 update statement
<update id="update" parameterType="map">
	UPDATE t_test
		SET num = #{num}
	WHERE id = #{id}
</update>
 delete statement
<delete id="delById" parameterType="long">
	DELETE FROM t_test
		WHERE id = #{id}
</delete>
 

 

 When developing with MyBatis, these configurations are the most frequently dealt with, so when writing SQL, it must be standardized.

 

 

4. Dynamic SQL

Another place where MyBatis is powerful is dynamic SQL. MyBatis employs powerful OGNL-based expressions to eliminate other elements.

(1)、if

What dynamic SQL usually does is conditionally include part of a where clause. E.g:

<select id="query" parameterType="map" resultMap="baseMap">
	SELECT <include refid="baseResult"/>
		FROM t_test
	WHERE 1=1
	  <if test="id!=0">
               AND id = #{id}
          </if>   
</select>

 It is still based on the previous SELECT statement, but a dynamic conditional additional statement is added. At this time, if id!=0, AND id = #{id} will be executed, and if id==0, this sentence will not be executed.

Dynamically embodied.

 

(2)、choose, when, otherwise

Sometimes, we don't want to use all the conditional statements, but just choose one or two of them. For this situation, MyBatis provides the choose element, which is a bit like a switch statement in Java.

 

<select id="query" resultType="Blog">
	SELECT <include refid="baseResult"/>
		FROM t_test
	WHERE 1=1
	  <choose>
		<when test="flag == 1">
		  AND id> #{id}
		</when>
		<when test="flag == 2">
		  AND id= #{id}
		</when>
		<otherwise>
		  AND #{id} > id
		</otherwise>
	  </choose>
</select>
 At this time, different values ​​of the flag field are used, and the corresponding SQL statements are different.

 

 

(3), a very useful syntax for foreach

Another common necessity of dynamic SQL is the need to traverse a collection, usually when constructing an IN conditional statement. for example:

 

 

<select id="query" parameterType="map" resultMap="baseMap">
	SELECT <include refid="baseResult"/>
		FROM t_test
	WHERE ID in
	  <foreach collection="idList" item="item" index="index"  open="(" separator="," close=")">
			#{item}
	  </foreach>
</select>
 If you query for a set of ids, you can use foreach

 

ps: Regarding the use of exist in in, if the range of the id array is small, use in, and if the range of the id array is larger than the query table itself, use exist. In a word, scan from a small result set.

 

(4), like, is not a feature of MyBatis, it is only used occasionally. Don't use it indiscriminately, the performance is not good.

 

 

select * from my_tab  
where keywords like CONCAT('%',#{keywords},'%' )  

 

 

5. Common API

SqlSessionFactory rarely operates, so you don't have to remember the api deliberately, you can query it when needed. However, SqlSession has some APIs that are used very frequently. In the process of using it, I do not deliberately remember it, but also remember it.

These methods are used to execute SELECT, INSERT, UPDA ET and DELETE statements defined in the SQL-mapped XML file. They all explain themselves, each statement uses the ID property of the statement and the parameter object, the parameters can be native types (autoboxing or wrapper classes), JavaBeans, POJOs or Maps.

 

<T> T selectOne(String statement, Object parameter)//Only one piece of data is returned. If there are multiple results, an error will be reported. It is recommended to add limit 1 at the end of this type of select statement
<E> List<E> selectList(String statement, Object parameter)//Return multiple pieces of data
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)//Insert
int update(String statement, Object parameter)//更新
int delete(String statement, Object parameter)//Delete
As for using a mapper, that's all, no need. 

 

 

6. Integrate spring

6.1、SqlSessionFactoryBean

6.2、SqlSessionTemplate

To use the MyBatis-Spring module, you only need to include  the mybatis-spring-xxxjar  file and add the relevant dependencies to the classpath. The corresponding version can be found in http://www.mvnrepository.com/  maven central repository, or your own private server.

如果你使用 Maven,那么在 pom.xml 中加入下面的代码即可:

 

dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>x.x.x</version>
</dependency>
 这个时候,SqlSessionFactory,SqlSession就交给了spring管理。spring使用SqlSessionFactoryBean去代理SqlSessionFactory,使用SqlSessionTemplate去代理SqlSession。
import java.beans.PropertyVetoException;
import java.io.IOException;

import javax.sql.DataSource;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.support.TransactionTemplate;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
public class DbConfig {
	
	@Bean 
	public DataSource DataSource() throws PropertyVetoException{
		DruidDataSource ds = new DruidDataSource();
		
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl(XX);
		ds.setUsername(XX);
		ds.setPassword(XX);
		
                //配置数据库连接池
		return ds;
	}
	
	@Bean
	public SqlSessionFactoryBean SqlSessionFactoryBean() throws IOException, PropertyVetoException {
		SqlSessionFactoryBean fc = new SqlSessionFactoryBean();
		fc.setDataSource(DataSource());
		
		ResourcePatternResolver resoler = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader());
		
		fc.setMapperLocations(resoler.getResources("sql/*/*.xml"));//扫描sql包下面的子包下面的mapper xml文件
		
		return fc;
	}
	
	@Bean
	public SqlSessionTemplate SqlSessionTemplate() throws Exception {
		SqlSessionTemplate sqlSession = new SqlSessionTemplate(SqlSessionFactoryBean().getObject());
		
                //SqlSessionTemplate 是线程安全的,放心使用
		return sqlSession;
	}
	
	@Bean
	public DataSourceTransactionManager transactionManager() throws PropertyVetoException{
		DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
		transactionManager.setDataSource(DataSource());
		
		return transactionManager;
	}
	
	@Bean
	public TransactionTemplate TransactionTemplate() throws PropertyVetoException{
		TransactionTemplate tsTemplate = new TransactionTemplate();
		tsTemplate.setTransactionManager (transactionManager ());
		tsTemplate.setIsolationLevel(Isolation.DEFAULT.value());//The transaction level adopts the database default
		tsTemplate.setPropagationBehavior(Propagation.REQUIRED.value());//The default propagation behavior of things
		
		return tsTemplate;
	}
	
}
   important point:
 At this time, SqlSessionFactory and SqlSession are handed over to spring management. Spring uses SqlSessionFactoryBean to proxy SqlSessionFactory and SqlSessionTemplate to proxy SqlSession.
import java.beans.PropertyVetoException;
import java.io.IOException;

import javax.sql.DataSource;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.support.TransactionTemplate;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
public class DbConfig {
	
	@Bean 
	public DataSource DataSource() throws PropertyVetoException{
		DruidDataSource ds = new DruidDataSource();
		
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl(XX);
		ds.setUsername(XX);
		ds.setPassword(XX);
		
                //配置数据库连接池
		return ds;
	}
	
	@Bean
	public SqlSessionFactoryBean SqlSessionFactoryBean() throws IOException, PropertyVetoException {
		SqlSessionFactoryBean fc = new SqlSessionFactoryBean();
		fc.setDataSource(DataSource());
		
		ResourcePatternResolver resoler = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader());
		
		fc.setMapperLocations(resoler.getResources("sql/*/*.xml"));//扫描sql包下面的子包下面的mapper xml文件
		
		return fc;
	}
	
	@Bean
	public SqlSessionTemplate SqlSessionTemplate() throws Exception {
		SqlSessionTemplate sqlSession = new SqlSessionTemplate(SqlSessionFactoryBean().getObject());
		
                //SqlSessionTemplate 是线程安全的,放心使用
		return sqlSession;
	}
	
	@Bean
	public DataSourceTransactionManager transactionManager() throws PropertyVetoException{
		DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
		transactionManager.setDataSource(DataSource());
		
		return transactionManager;
	}
	
	@Bean
	public TransactionTemplate TransactionTemplate() throws PropertyVetoException{
		TransactionTemplate tsTemplate = new TransactionTemplate();
		tsTemplate.setTransactionManager(transactionManager());
		tsTemplate.setIsolationLevel(Isolation.DEFAULT.value());//事物级别采用数据库默认
		tsTemplate.setPropagationBehavior(Propagation.REQUIRED.value());//事物传播行为采用默认
		
		return tsTemplate;
	}
	
}
   注意点:

 (1)、在基本的 MyBatis 中,session 工厂可以使用 SqlSessionFactoryBuilder 来创建。而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来替代。

也可以使用xml配置,例如:

 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>
  The mapperLocations configuration is to scan the mapper xml configuration file under the package

 

(2) For things, use spring. About things, a sentence or two is not complete, it should be a separate page.

(3) SqlSessionTemplate is thread-safe and can be shared by multiple DAOs. The conscience of the industry! All code with pitfalls is not good code. 

 

How to use SqlSessionTemplate?

@Repository
public class TestRepository {
	@Autowired SqlSession session;
	
	public TTest queryById(long id){
		return session.selectOne("t_test.query", id);
	}
}

 

Concise but not simple. Simple in shape and complex in heart, this design is really awesome.

 

 

 

 --------------------------------------------------------------------------------------------------------------------------------

Summary: MyBatis is actually a semi-ORM persistence framework, but it is this feature that allows developers to use it more flexibly, customize SQL statements, and directly improve performance.

If hibernate is an M16, then MyBatis is an AK47.

I love MyBatis.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326309164&siteId=291194637