1, Annotation
I've been familiar with the basic use of MyBatis. For some simple sql statements, such as adding, deleting, modifying and querying a table, you can use the annotations provided by MyBatis to save the steps of writing mapping files and complex multi table queries. It is recommended to use mapping files
1. Select notes
Using the Select annotation, the database query operation can be realized
Query the department according to the department number
Entity class:
copy@Data @AllArgsConstructor @NoArgsConstructor public class Dept implements Serializable { /** * Department number */ private Integer deptno; /** * Department name */ private String dname; /** * address */ private String loc; }
Define interface method:
copypublic interface DeptMapper { /** * Query department by department number * @param deptno * @return */ @Select("select * from dept where deptno = #{deptno}") Dept findDeptByDeptno(int deptno); }
The method of using parameters in SQL statements is the same as that in #{} the mapping file. You can also use annotations to specify the name of parameters
copypublic interface DeptMapper { /** * Query Department No * @param deptno * @return */ @Select("select * from dept where deptno = #{no}") Dept findDeptByDeptno(@Param("no") int deptno); }
Test method:
copy//Query department by department number @Test public void test1() { DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.findDeptByDeptno(10); System.out.println(dept); }
2. Insert notes
Add a new department information
Define interface method:
copy/** * Add a new department information * * @param dept * @return */ @Insert("insert into dept values(#{deptno},#{dname},#{loc})") int addDept(Dept dept);
sql parameters use attribute names
Test method:
copy//Add a new department information @Test public void test2() { DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = new Dept(50,"ALGORITHM","Paris"); int rows = mapper.addDept(dept); System.out.println(rows); sqlSession.commit(); }
3. Update notes
Update department information according to department number
Define interface method:
copy/** * Update department information according to department number * @param dept * @return */ @Update("update dept set dname = #{dname}, loc = #{loc} where deptno = #{deptno}") int updateDept(Dept dept);
Test method:
copy//Update department information according to department number @Test public void test3() { DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = new Dept(50,"ALGORITHM","Tokyo"); int rows = mapper.updateDept(dept); System.out.println(rows); sqlSession.commit(); }
4. Delete annotation
Delete department according to department number
Define interface method:
copy/** * Delete department according to department number * @param deptno * @return */ @Delete("delete from dept where deptno = #{deptno}") int deleteDeptbyDeptno(int deptno);
Test method:
copy//Delete department according to department number @Test public void test4() { DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); int rows = mapper.deleteDeptbyDeptno(50); System.out.println(rows); sqlSession.commit(); }
2, Cache configuration
MyBatis has its own L1 cache and L2 cache, and also supports third-party cache, such as redis and ehcache
1. L1 cache
The L1 cache is enabled by default and exists in each SqlSession object. For the same query, if it exists in the L1 cache, it will not go to the database and return directly
For test1 method, obtain two mappers through sqlSession and perform the same operation. Finally, check whether the query result is the same object:
copy//Query department by department number @Test public void test1() { DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.findDeptByDeptno(10); System.out.println(dept); DeptMapper mapper2 = sqlSession.getMapper(DeptMapper.class); Dept dept2 = mapper2.findDeptByDeptno(10); System.out.println(dept2); System.out.println(dept == dept2); }
result:

2. L2 cache
The L2 cache can span sqlsessions. The condition is that it is created by the same SqlSessionFactory. The L2 cache is closed by default. The following steps are required to open it
- 2.1 global switch
It is configured in the MyBatis core configuration file and supports L2 cache
copy<settings> ... <!--Enable L2 cache--> <setting name="cacheEnabled" value="true"/> </settings>
- 2.2 enable L2 cache in mapper
- Opening method in java: Use CacheNamespace annotation on interface
copy@CacheNamespace public interface DeptMapper {
- Opening method in mapping file: Use the cache tag and set useCache="true" for queries that need to be cached
copy<mapper namespace="com.aruba.mapper.DeptMapper"> <cache/> <!-- Dept findDeptByDeptno(@Param("no") int deptno);--> <select id="findDeptByDeptno" resultType="dept" useCache="true"> select * from dept where deptno = #{no} </select> </mapper>
In addition, the entity class needs to implement the serialization interface because it may be stored on disk
- 2.3 commit or close operation of sqlsession
SqlSession will first look in the L2 cache. If it does not exist, query the database and put the data into the L2 cache when commit() or close()
Test method:
copypublic class Test1 { private SqlSession sqlSession; private SqlSession sqlSession2; @Before public void init() throws IOException { SqlSessionFactoryBuilder sb = new SqlSessionFactoryBuilder(); // Pass in the configuration file as a parameter SqlSessionFactory sqlSessionFactory = sb.build(Resources.getResourceAsStream("sqlMapConfig.xml")); sqlSession = sqlSessionFactory.openSession(); sqlSession2 = sqlSessionFactory.openSession(); } //Query department by department number - L2 cache @Test public void test5() { DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.findDeptByDeptno(10); System.out.println(dept); sqlSession.commit(); DeptMapper mapper2 = sqlSession2.getMapper(DeptMapper.class); Dept dept2 = mapper2.findDeptByDeptno(10); System.out.println(dept2); } @After public void release() { if (sqlSession != null) sqlSession.close(); if (sqlSession2 != null) sqlSession2.close(); } }
result:

Only one sql was executed
3. Third party cache
When it comes to distributed systems, the cache provided by MyBatis cannot meet the requirements. Ehcache is used as the third-party cache below
Import dependency:
copy<dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-nop</artifactId> <version>1.7.2</version> </dependency>
Create the configuration file ehcache. Exe in the resources directory xml:
copy<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <diskStore path="D:\aruba\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
L2 cache configuration:
- In Java: CacheNamespace annotation, specifying the Class using the cache
copy@CacheNamespace(implementation = EhcacheCache.class) public interface DeptMapper {
- In the mapping file: Cache tag, which specifies the full class name of the cache
copy<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
3, Reverse engineering
MyBatis officially provides a reverse engineering tool to automatically generate the entity classes, mapping files and interfaces corresponding to the table, and automatically realize some basic additions, deletions, modifications and queries
1. Import dependency:
copy<!-- Code generation tool jar --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency>
2. Create generatorconfig. In the resources directory xml:
copy<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- Remove automatically generated comments true: Yes: false:no --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--Database connection information: driver class, connection address, user name and password --> <!-- <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="123"> </jdbcConnection> --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true" userId="root" password="root"> </jdbcConnection> <!-- default false,hold JDBC DECIMAL and NUMERIC Type resolves to Integer,by true Shi Ba JDBC DECIMAL and NUMERIC Type resolves to java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:generate PO Class location --> <javaModelGenerator targetPackage="com.aruba.pojo" targetProject=".\reverseMyBatis\src\main\java"> <!-- enableSubPackages:Whether to let schema As the suffix of the package --> <property name="enableSubPackages" value="false" /> <!-- The space before and after the value returned from the database is cleaned up --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper Location where the mapping file is generated --> <sqlMapGenerator targetPackage="com.aruba.mapper" targetProject=".\reverseMyBatis\src\main\java"> <!-- enableSubPackages:Whether to let schema As the suffix of the package --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage: mapper Location of interface generation --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.aruba.mapper" targetProject=".\reverseMyBatis\src\main\java"> <!-- enableSubPackages:Whether to let schema As the suffix of the package --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- Specify the generated database table --> <table tableName="dept" domainObjectName="Dept" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" > <columnOverride column="id" javaType="Integer" /> </table> </context> </generatorConfiguration>
3. Run the following code:
Manually modify generatorconfig. In the compiled target directory Absolute path to XML
copypublic class GeneratorSqlmap { public void generator() throws Exception { List<String> warnings = new ArrayList<String>(); boolean overwrite = true; // Manual modification required File configFile = new File("F:\\idelworkspace\\mybatis_study\\reverseMyBatis\\target\\classes\\generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap(); generatorSqlmap.generator(); } catch (Exception e) { e.printStackTrace(); } } }
Generated results:

It comes with some implementations:
copypublic interface DeptMapper { int deleteByPrimaryKey(Integer deptno); int insert(Dept record); int insertSelective(Dept record); Dept selectByPrimaryKey(Integer deptno); int updateByPrimaryKeySelective(Dept record); int updateByPrimaryKey(Dept record); }