MyBatis: CRUD operation and configuration analysis

Episode review: MyBatis: The first program

Table of contents

namespace

select

Requirement: Query users by id

1. Add the corresponding method in UserMapper

2. Add Select statement in UserMapper.xml

3. Test in the test class

Class Exercise: Query Users by Password and Name

insert

Requirement: Add a user to the database

1. Add the corresponding method in the UserMapper interface

2. Add insert statement in UserMapper.xml

3. Test

update

Requirement: Modify user information

1. Similarly, write interface methods

2. Write the corresponding configuration file SQL

3. Test

delete

Requirement: delete a user based on id

1. Similarly, write interface methods

2. Write the corresponding configuration file SQL

3. Test

summary:

Thinking questions How to write fuzzy query like statement?

Configuration parsing

core configuration file

environments element

mappers element

mappers

Import resource method

Mapper file

PropertiesOptimization

The first step; create a new db.properties in the resource directory

Step 2: Import the file into the properties configuration file

typeAliases optimization

Other Configuration Browse

set up

type handler

object factory

Lifecycle and Scope

Scope and life cycle

scope understanding


namespace

  1. Rename the UserMapper interface in the above case to UserDao;

  2. Change the namespace in UserMapper.xml to the path of UserDao.

  3. test again

in conclusion:

The name in the namespace in the configuration file is the complete package name corresponding to the Mapper interface or Dao interface, and must be consistent!

select

  • The select tag is one of the most commonly used tags in mybatis

  • The select statement has many attributes to configure each SQL statement in detail

    • SQL statement return value type. [full class name or alias]

    • The parameter type of the incoming SQL statement. [Universal Map, you can try to use it more]

    • unique identifier in the namespace

    • There is a one-to-one correspondence between the method name in the interface and the SQL statement ID in the mapping file

    • id

    • parameterType

    • resultType

Requirement: Query users by id

1. Add the corresponding method in UserMapper

public interface UserMapper {
   //查询全部用户
   List<User> selectUser();
   //根据id查询用户
   User selectUserById(int id);
}

2. Add Select statement in UserMapper.xml

<select id="selectUserById" resultType="com.kuang.pojo.User">
select * from user where id = #{id}
</select>

3. Test in the test class

@Test
public void tsetSelectUserById() {
   SqlSession session = MybatisUtils.getSession();  //获取SqlSession连接
   UserMapper mapper = session.getMapper(UserMapper.class);
   User user = mapper.selectUserById(1);
   System.out.println(user);
   session.close();
}

Class Exercise: Query Users by Password and Name

Idea 1: Pass parameters directly in the method

1. Add the @Param attribute before the parameters of the interface method

2. When writing a Sql statement, you can directly take the value set in @Param, and you don’t need to set the parameter type separately

//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);

/*
   <select id="selectUserByNP" resultType="com.kuang.pojo.User">
     select * from user where name = #{username} and pwd = #{pwd}
   </select>
*/

Idea 2: Use the universal Map

1. In the interface method, the parameters are directly passed to the Map;

User selectUserByNP2(Map<String,Object> map);

2. When writing SQL statements, you need to pass the parameter type, and the parameter type is map

<select id="selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>

3. When using the method, the key of the Map can be the value taken in sql, and there is no order requirement!

Map<String, Object> map = new HashMap<String, Object>();
map.put("username","小明");
map.put("pwd","123456");
User user = mapper.selectUserByNP2(map);

Summarize:

If there are too many parameters, we can consider using Map to implement directly. If there are fewer parameters, just pass the parameters directly.

insert

We generally use the insert tag for insert operations, and its configuration is similar to that of the select tag!

Requirement: Add a user to the database

1. Add the corresponding method in the UserMapper interface

//添加一个用户
int addUser(User user);

2. Add insert statement in UserMapper.xml

<insert id="addUser" parameterType="com.kuang.pojo.User">
    insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>

3. Test

@Test
public void testAddUser() {
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);
   User user = new User(5,"王五","zxcvbn");
   int i = mapper.addUser(user);
   System.out.println(i);
   session.commit(); //提交事务,重点!不写的话不会提交到数据库
   session.close();
}

Note: Add, delete, and modify operations need to submit transactions!

update

We generally use the update tag for update operations, and its configuration is similar to the select tag!

Requirement: Modify user information

1. Similarly, write interface methods

//修改一个用户
int updateUser(User user);

2. Write the corresponding configuration file SQL

<update id="updateUser" parameterType="com.kuang.pojo.User">
  update user set name=#{name},pwd=#{pwd} where id = #{id}
</update>

3. Test

@Test
public void testUpdateUser() {
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);
   User user = mapper.selectUserById(1);
   user.setPwd("asdfgh");
   int i = mapper.updateUser(user);
   System.out.println(i);
   session.commit(); //提交事务,重点!不写的话不会提交到数据库
   session.close();
}

delete

We generally use the delete tag to delete, and its configuration is similar to the select tag!

Requirement: delete a user based on id

1. Similarly, write interface methods

//根据id删除用户
int deleteUser(int id);

2. Write the corresponding configuration file SQL

<delete id="deleteUser" parameterType="int">
  delete from user where id = #{id}
</delete>

3. Test

@Test
public void testDeleteUser() {
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);
   int i = mapper.deleteUser(5);
   System.out.println(i);
   session.commit(); //提交事务,重点!不写的话不会提交到数据库
   session.close();
}

summary:

  • All additions, deletions, and modifications require a transaction to be committed!

  • For all common parameters of the interface, write @Param parameters as much as possible, especially when there are multiple parameters, you must write them!

  • Sometimes according to business needs, you can consider using map to pass parameters!

  • In order to standardize the operation, in the SQL configuration file, we try to write both the Parameter parameter and the resultType!

Thinking questions  How to write fuzzy query like statement?

Type 1: Add sql wildcards in Java code.

string wildcardname = “%smi%”;
list<name> names = mapper.selectlike(wildcardname);

<select id=”selectlike”>
select * from foo where bar like #{value}
</select>

Type 2: Splicing wildcards in sql statements will cause sql injection

string wildcardname = “smi”;
list<name> names = mapper.selectlike(wildcardname);

<select id=”selectlike”>
    select * from foo where bar like "%"#{value}"%"
</select>

Configuration parsing

core configuration file

  • mybatis-config.xml system core configuration file

  • MyBatis configuration files contain information about settings and properties that deeply affect MyBatis behavior.

  • The content that can be configured is as follows:

configuration (configuration) 
properties (attribute) 
settings (setting) 
typeAliases (type alias) 
typeHandlers (type processor) 
objectFactory (object factory) 
plugins (plug-in) 
environments (environment configuration) 
environment (environment variable) 
transactionManager (transaction manager) 
dataSource ( Data source) 
databaseIdProvider (database vendor ID) 
mappers (mapper) 
<!-- Pay attention to the order of element nodes! If the order is wrong, an error will be reported -->

We can read the dtd header file above mybatis-config.xml!

environments element

<environments default="development">
 <environment id="development">
   <transactionManager type="JDBC">
     <property name="..." value="..."/>
   </transactionManager>
   <dataSource type="POOLED">
     <property name="driver" value="${driver}"/>
     <property name="url" value="${url}"/>
     <property name="username" value="${username}"/>
     <property name="password" value="${password}"/>
   </dataSource>
 </environment>
</environments>
  • Configure multiple sets of operating environments of MyBatis, map SQL to multiple different databases, and must specify one of them as the default operating environment (specified by default)

  • Child element node: environment

    • The dataSource element configures the resource of a JDBC connection object using the standard JDBC data source interface.

    • The data source must be configured.

    • There are three built-in data source types

      type="[UNPOOLED|POOLED|JNDI]")
    • unpooled: The implementation of this data source simply opens and closes the connection each time it is requested.

    • pooled : The implementation of this data source uses the concept of "pooling" to organize JDBC connection objects, which is a popular processing method to make concurrent Web applications respond to requests quickly.

    • jndi: This data source is implemented for use in containers such as Spring or application servers. The container can configure the data source centrally or externally, and then place a reference to the JNDI context.

    • There are also many third-party implementations of data sources, such as dbcp, c3p0, druid, etc....

    • Details: Click to view official documents

    • Neither transaction manager type requires any properties to be set.

    • A specific set of environments can be distinguished by setting the id, and the id is guaranteed to be unique!

    • Child element node: transactionManager - [ Transaction Manager ]

      <!-- Syntax--> 
      <transactionManager type="[ JDBC | MANAGED ]"/>
    • Child element node: data source (dataSource)

mappers element

mappers

  • mapper: defines the mapping SQL statement file

  • Now that the behavior and other elements of MyBatis have been configured, we are now going to define the SQL mapping statement. But first we need to tell MyBatis where to find these statements. Java does not provide a good way to automatically find this, so the best way is to tell MyBatis where to find the mapping file. You can use classpath-relative resource references, or fully qualified resource locators ( file:///including URLs), or class and package names, etc. The mapper is one of the core components in MyBatis. Before MyBatis 3, only the xml mapper is supported, that is, all SQL statements must be configured in the xml file. Starting from MyBatis 3, the interface mapper is also supported. This mapper method allows annotations to define SQL statements in the form of Java code, which is very concise.

Import resource method

<!-- 使用相对于类路径的资源引用 -->
<mappers>
 <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
 <mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<!--
使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
 <mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!--
将包内的映射器接口实现全部注册为映射器
但是需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
 <package name="org.mybatis.builder"/>
</mappers>

Mapper file

<?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="com.kuang.mapper.UserMapper">
   
</mapper>
  • Namespace Chinese meaning: namespace, the role is as follows:

    • The name of the namespace must be the same as that of an interface

    • The method in the interface should correspond to the sql statement id in the mapping file

    1. The id of namespace and sub-element is jointly guaranteed to be unique, distinguishing different mappers

    2. Binding DAO interface

    3. namespace naming rules: package name + class name

The real power of MyBatis lies in its mapped statements, which is where its magic lies. Because of how powerful it is, the mapper's XML file is relatively simple. If you compare this with the JDBC code that has the same functionality, you'll immediately see that you've saved almost 95% of the code. MyBatis is built with a focus on SQL to save you as much hassle as possible.

PropertiesOptimization

These properties of the database are externally configurable and dynamically replaceable, either in a typical Java properties file, or passed through sub-elements of the properties element. Specific official documents

Let's optimize our configuration file

The first step; create a new db.properties in the resource directory

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=123456

Step 2: Import the file into the properties configuration file

<configuration>
   <!--导入properties文件-->
   <properties resource="db.properties"/>

   <environments default="development">
       <environment id="development">
           <transactionManager type="JDBC"/>
           <dataSource type="POOLED">
               <property name="driver" value="${driver}"/>
               <property name="url" value="${url}"/>
               <property name="username" value="${username}"/>
               <property name="password" value="${password}"/>
           </dataSource>
       </environment>
   </environments>
   <mappers>
       <mapper resource="mapper/UserMapper.xml"/>
   </mappers>
</configuration>

typeAliases optimization

A type alias is to set a short name for a Java type. It is only related to XML configuration and exists only to reduce the redundancy of fully qualified names of classes.

<!--配置别名,注意顺序-->
<typeAliases>
   <typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>

When configured like this, Userit can be used wherever it is used com.kuang.pojo.User.

You can also specify a package name, and MyBatis will search for the required Java Bean under the package name, for example:

<typeAliases>
   <package name="com.kuang.pojo"/>
</typeAliases>

Each Java Bean com.kuang.pojoin , in the absence of annotations, will use the bean's initial lowercase unqualified class name as its alias.

If there is an annotation, the alias is its annotation value. See the example below:

@Alias("user")
public class User {
  ...
}

Go to the official website to check some default type aliases of Mybatis!

Other Configuration Browse

set up

  • Settings (settings) related => view help documents

    • lazy loading

    • log implementation

    • cache on off

  • An example of a fully configured settings element is as follows:

    <settings>
     <setting name="cacheEnabled" value="true"/>
     <setting name="lazyLoadingEnabled" value="true"/>
     <setting name="multipleResultSetsEnabled" value="true"/>
     <setting name="useColumnLabel" value="true"/>
     <setting name="useGeneratedKeys" value="false"/>
     <setting name="autoMappingBehavior" value="PARTIAL"/>
     <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
     <setting name="defaultExecutorType" value="SIMPLE"/>
     <setting name="defaultStatementTimeout" value="25"/>
     <setting name="defaultFetchSize" value="100"/>
     <setting name="safeRowBoundsEnabled" value="false"/>
     <setting name="mapUnderscoreToCamelCase" value="false"/>
     <setting name="localCacheScope" value="SESSION"/>
     <setting name="jdbcTypeForNull" value="OTHER"/>
     <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
    </settings>

type handler

  • No matter when MyBatis sets a parameter in a prepared statement (PreparedStatement) or fetches a value from the result set, it will use a type processor to convert the obtained value into a Java type in an appropriate way.

  • You can override type handlers or create your own to handle unsupported or non-standard types. 【Understanding】

object factory

  • Every time MyBatis creates a new instance of a result object, it does so using an ObjectFactory instance.

  • All the default object factory needs to do is instantiate the target class, either via the default constructor, or via the parametric constructor if the parameter map exists.

  • If you want to override the default behavior of an object factory, you can do so by creating your own object factory. 【Understanding】

Lifecycle and Scope

Scope and life cycle

Understanding the different scope and lifecycle classes we've discussed so far is crucial, as incorrect usage can lead to very serious concurrency issues.

We can first draw a flow chart and analyze the execution process of Mybatis!


scope understanding

  • The function of SqlSessionFactoryBuilder is to create SqlSessionFactory. After the creation is successful, SqlSessionFactoryBuilder loses its function, so it can only exist in the method of creating SqlSessionFactory, and do not let it exist for a long time. So the best scope for an instance of SqlSessionFactoryBuilder is method scope (that is, local method variables).

  • SqlSessionFactory can be considered as a database connection pool, its role is to create SqlSession interface objects. Because the essence of MyBatis is the operation of Java on the database, the life cycle of SqlSessionFactory exists in the entire MyBatis application, so once the SqlSessionFactory is created, it must be saved for a long time until the MyBatis application is no longer used, so the life of SqlSessionFactory can be considered The cycle is equivalent to the application cycle of MyBatis.

  • Since SqlSessionFactory is a connection pool to the database, it occupies the connection resources of the database. If you create multiple SqlSessionFactories, then there will be multiple database connection pools, which is not conducive to the control of database resources, and will also lead to the consumption of database connection resources, system downtime, etc., so try to avoid such situations.

  • Therefore, in general applications, we often want SqlSessionFactory as a singleton, so that it can be shared in the application. So the best scope for SqlSessionFactory is application scope.

  • If SqlSessionFactory is equivalent to a database connection pool, then SqlSession is equivalent to a database connection (Connection object). You can execute multiple SQLs in a transaction, and then submit or rollback the transaction through its commit, rollback and other methods. So it should survive in a business request. After processing the entire request, it should close the connection and return it to SqlSessionFactory, otherwise the database resources will be exhausted quickly and the system will be paralyzed, so use try...catch ...finally... statement to ensure that it closes properly.

  • So the best scope for SqlSession is request or method scope.


Guess you like

Origin blog.csdn.net/weixin_45987577/article/details/126636828