1, hello world
1. Environmental construction
create maven web project mybatis01 and add maven dependencies as follows.
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency>
2. Data preparation
to facilitate learning, execute the following table creation commands and insert data commands.
CREATE TABLE `pet` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `weight` double NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4; insert into `pet`(`id`,`name`,`weight`) values (1,'tearful',4.5); insert into `pet`(`id`,`name`,`weight`) values (2,'In vain',5.6); insert into `pet`(`id`,`name`,`weight`) values (3,'black',7.8); insert into `pet`(`id`,`name`,`weight`) values (4,'Honghong',9);
3. Configure core profile
configure the mybatis core configuration file: mybatis-conf.xml. Create this file in the resource directory. The contents are as follows:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> </configuration>
be careful:
The type of dataSource can be configured as one of its built-in types, UNPOOLED, POOLED and JNDI.
- UNPOOLED, MyBatis will create a new connection for each database operation and close it. This method is suitable for simple applications with only a small number of concurrent users.
- POOLED, MyBatis will create a database connection pool, and a connection in the connection pool will be used as a database operation. Once the database operation is completed, MyBatis will return this connection to the connection pool. This approach is often used in development or test environments.
- JNDI and MyBatis obtain the database connection from the application server to the configured JNDI data source dataSource. In a production environment, this approach is preferred.
4. Log configuration (optional)
in order to monitor the execution of mybatis, we print the operation of relevant programs through logback. Add the log configuration file logback.xml under resource
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!--Console--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p --- [%t] %-40.40logger{39} : %m%n</pattern> </encoder> </appender> <!--root logger--> <root level="DEBUG" additivity="false"> <appender-ref ref="console"/> </root> </configuration>
After adding the file, the operation status of mybatis, the SQL sent, the data filled in by SQL and the number of returned data are printed and displayed on the console.
5. Create entity
create corresponding entities and add corresponding getter and setter methods. Because mybatis uses reflection to complete the encapsulation of objects, entities must need a parameterless construction method. If you need to output an object, you also need to override its toString method
public class Pet{ private Integer id; private String name; private Double weight }
6. Create Mapper file
all database operations of mybatis are completed through mapper files. Mapper files are generally stored in the resource/mapper / directory.
create the mapping file * Mapper.xml corresponding to the entity class, as shown in the following code:
<?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="cn.hxzy.mapper.petMapper"> <select id="getById" parameterType="int" resultType="cn.hxzy.entity.Pet"> select * from pet where id=#{id} </select> </mapper>
be careful:
parameterType: parameter type
resultType: method return type (if the return is a collection, the return type adds the full path of the type of the collection to store the object)
Whether it is a parameter type or a return type, a custom class needs to write the full pathname of the class.
7. Register mapper file
register the above * Mapper.xml in the mybatis core configuration file mybatis-conf.xml
<mappers> <mapper resource="mapper/PetMapper.xml"/> </mappers>
The following is an explanation of these configuration files:
1. The configuration file mybatis-conf.xml is used by mybatis to establish sessionFactory, which mainly contains contents related to database connection.
2. mybatis-conf.xml contains the XML configuration file containing the classes to be mapped.
3. The * Mapper.xml file mainly defines various SQL statements, parameters of these statements, types to be returned, etc.
8. Operation test
create the main method and complete the relevant tests
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.IOException; import java.io.Reader; public class MainTest { public static void main(String[] args) throws IOException { //Load the core configuration file of mybatis (it also loads the associated mapping file) Reader reader = Resources.getResourceAsReader("mybatis-conf.xml"); //Build a factory for sqlSession SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //Create an sqlSession that can execute sql in the mapping file SqlSession session = sessionFactory.openSession(); Object o = session.selectOne("cn.hxzy.mapper.petMapper.getById",3); System.out.println(o); } }
be careful:
1. The original intention of selectone is to query a single. When multiple results appear during query, the following error will be reported: if the query is a collection, use the selectList method.
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
2.SqlSessionFactory thread safety can be designed as a singleton
3.SqlSession thread is unsafe and cannot be a public variable of a class
practice:
1. Create the project fruit01, create the fruit (id, name, color) entity and the corresponding database table in the project, and complete the functions of querying fruits and all fruits according to id.
Reference code:
<?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="cn.hxzy.mapper.fruitMapper"> <select id="getById" parameterType="int" resultType="cn.hxzy.entity.Fruit"> select * from fruit where id=#{id} </select> <select id="findAll" resultType="cn.hxzy.entity.Fruit"> select * from fruit where id=#{id} </select> </mapper>
2, Interface notes (understand)
in the previous section, we implemented a simple query of mybatis. There are also simpler methods. We use interfaces that reasonably describe parameters and return values of SQL statements (such as IUserMapper.java), so that we can now avoid using configuration files like UserMapper.xml, which is simpler, safer, and less prone to string text and conversion errors, The following is the detailed process of project creation:
create an interface: PetMapper, and declare the corresponding operation method in it
public interface PetMapper { @Insert("insert into pet(name,weight) values (#{name},#{weight})") int add(Pet pet); @Select("select * from pet where id=#{id}") Pet getById(int id); }
Register the mapper interface in mybatis-conf.xml
<mapper class="cn.hxzy.mybatis.mapper.PetMapper"/>
The test class modifies the following location to complete the test
public static void main(String[] args) throws IOException { //Load the configuration file for mybatis (it also loads the associated mapping file) Reader reader = Resources.getResourceAsReader("mybatis-conf.xml"); //Build a factory for sqlSession SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //Create an sqlSession that can execute sql in the mapping file SqlSession session = sessionFactory.openSession(); //Identity string of mapping sql //Execute the query and return the sql of a unique user object Pet pet = session.getMapper(PetMapper.class ).getById( 1 ); //The method is called according to the mapper's namespace and id System.out.println(pet); }
So far, the query method based on interface annotation is completed, and SQL is difficult to be dynamic when using annotation, so the most commonly used is the combination of interface and xml.
Note: the session is not automatically submitted by default when the database is added, deleted or modified. You need to manually call session.commit(); Submit the operation.
practice:
1. Create the project pet01 and complete the basic pet operations with annotations (add, modify according to id, delete according to id, query all), and use unit test to detect the availability of the method.
2. Complete and test the basic operation of fruit (id, name, color) with full annotation in project pet01.
Reference answer:
PetMapper
import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import java.util.List; public interface PetMapper { @Insert("insert into pet(name,weight) values (#{name},#{weight})") int add(Pet pet); @Update("update pet set name=#{name},weight=#{weight} where id=#{id}") int update(Pet pet); @Delete("delete from pet where id =#{id}") int deleteById(int id); @Select("select * from pet") List<Pet> findAll(); }
unit testing
import cn.hxzy.entity.Pet; import cn.hxzy.mapper.PetMapper; 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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.Reader; import java.util.List; public class MainTest { SqlSession session; @Before public void before() throws IOException { Reader reader = Resources.getResourceAsReader("mybatis-conf.xml"); //Build a factory for sqlSession SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //Create an sqlSession that can execute sql in the mapping file session = sessionFactory.openSession(true); reader.close(); } @Test public void add() throws IOException { PetMapper mapper = session.getMapper(PetMapper.class); Pet pet = new Pet(); pet.setName("tearful"); pet.setWeight(12.5); mapper.add(pet); } @Test public void update() throws IOException { PetMapper mapper = session.getMapper(PetMapper.class); Pet pet = new Pet(); pet.setId(6); pet.setName("tearful"); pet.setWeight(12.5); mapper.update(pet); } @Test public void delete() throws IOException { PetMapper mapper = session.getMapper(PetMapper.class); mapper.delete(2); } @Test public void findAll() throws IOException { PetMapper mapper = session.getMapper(PetMapper.class); List<Pet> all = mapper.findAll(); System.out.println(all); } @After public void close() { session.close(); } }
3, Interface with xml
in the actual development, the interface is mostly used in combination with XML, which can not only reduce the probability of using string error prone when writing statement, but also display the contents of XML after compilation, so as to facilitate later SQL optimization. Finally, the combination of interface and XML also reflects the high cohesion and low coupling characteristics of java programs. To use the interface in combination with XML, you need to register the applied XML in mybatis-conf.xml.
<mappers> <mapper resource="mapper/PetMapper.xml"></mapper> </mappers>
the namespace in Mapper.xml points to the class path of the interface, and the methods in the interface correspond to the id in XML.
when calling, it is still called through the interface, but the annotation of the interface needs to be removed.
PetDao mapper = session.getMapper(PetDao.class); System.out.println(mapper.queryById(87));
in this way, we can use the dynamic SQL of mybatis and call through the interface to reduce the possibility of writing errors.
4, Basic operations of database tables
various database operations can be well completed through the combination of interface and mapper.xml. Add the corresponding CRUD statement in mapper.xml to correspond with the method name in the interface to complete the relevant operations. The corresponding mapper.xml can use insert, delete, update, select and other nodes to complete the corresponding operations, and specify the corresponding parameter type and return type.
<insert id="insert" parameterType="cn.hxzy.entity.Pet"> insert into pet(name,weight) values(#{name},#{weight}) </insert> <delete id="delete" parameterType="int"> delete from pet where id=#{id} </delete> <select id="getById" parameterType="int" resultType="cn.hxzy.entity.Pet"> select * from pet where id=#{id} </select> <select id="selectAll" resultType="cn.hxzy.entity.Pet"> select * from pet </select>
Note: if SQL contains special characters, use CDATA tag
<if test="ageEnd!=null"><![CDATA[<]]> #{ageEnd}</if>
be careful:
- The id of xml corresponds to the method name of the interface.
- Transactions must be added to all methods except query methods
SqlSession session = sessionFactory.openSession(); session.getMapper( UserMapper.class ).insertUser( new User( "222",1 ) ); session.commit();
session has corresponding commit and rollback methods
Or let the session submit automatically when obtaining the session
SqlSession session = sessionFactory.openSession(true);
practice:
1. Create the project fruit02. Use the combination of xml and interface to complete the basic operations of the fruit table (add, modify according to id, delete according to id, query all) and use the unit test to test the availability of the method.
Reference code:
mapper interface
public interface FruitMapper { int deleteByPrimaryKey(Integer id); int insert(Fruit record); List<Fruit> selectAll(); int updateByPrimaryKey(Fruit record); }
mapper xml
<?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="cn.hxzy.mapper.FruitMapper"> <resultMap id="BaseResultMap" type="cn.hxzy.entity.Fruit"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="name" jdbcType="VARCHAR" property="name"/> <result column="color" jdbcType="VARCHAR" property="color"/> </resultMap> <sql id="Base_Column_List"> id, `name`, color </sql> <select id="selectAll" parameterType="java.lang.Integer" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from fruit </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from fruit where id = #{id,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="cn.hxzy.entity.Fruit"> insert into fruit (`name`, color) values (#{name,jdbcType=VARCHAR}, #{color,jdbcType=VARCHAR}) </insert> <update id="updateByPrimaryKey" parameterType="cn.hxzy.entity.Fruit"> update fruit set `name` = #{name,jdbcType=VARCHAR}, color = #{color,jdbcType=VARCHAR} where id = #{id,jdbcType=INTEGER} </update> </mapper>
unit testing
import cn.hxzy.entity.Fruit; import cn.hxzy.mapper.FruitMapper; 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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.Reader; import java.util.List; public class MainTest { SqlSession session; @Before public void getSession() throws IOException { Reader reader = Resources.getResourceAsReader("mybatis-conf.xml"); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); session = sessionFactory.openSession(true); reader.close(); } @Test public void add() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); Fruit fruit = new Fruit(); fruit.setName("apple"); fruit.setColor("red"); mapper.insert(fruit); } @Test public void select() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); List<Fruit> fruits = mapper.selectAll(); System.out.println(fruits); } @Test public void delete() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); int i = mapper.deleteByPrimaryKey(1); System.out.println("Database impact:" + i); } @Test public void update() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); Fruit fruit = new Fruit(); fruit.setId(1); fruit.setName("apple"); fruit.setColor("white"); mapper.insert(fruit); } @After public void close() { session.close(); } }
5, Optimize connection profile
Database connection information is dedicated to one file
Create db.properties file under resource
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///mybatis?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8 jdbc.username=root jdbc.password=123456
Modify profile
<properties resource="db.properties"/> <property name="driver" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" />
6, Alias Manager (understand)
define aliases for entity classes, simplify references in sql mapping XML files, and add them in mybatis-conf.xml files
<typeAliases> <typeAlias type="cn.hxzy.entity.Pet" alias="pet"/> </typeAliases>
Type: Specifies the full class name of the type to be aliased. The default alias is the class name (case insensitive);
Alias: specify a new alias
In this way, you can manipulate the database by using aliases
<select id="selectById" parameterType="int" resultType="pet"> select * from pet where id=#{id} </select>
typeAliases batch aliasing
Package: alias all classes in a package in batch.
<typeAliases> <package name="cn.hxzy.ibatis.bean"/> </typeAliases>
Name: set a default alias for each class of the current package and all the following descendant packages (the same as the class name and case insensitive)
In the case of batch aliasing, use the @ Alias annotation to specify a new Alias for a type.
7, mybatisX plug-in
function
1. The mapper interface jumps back and forth with xml.
2. The mapper method automatically generates xml.
3.xml check whether the id is consistent with the interface method name.
8, Obtain self incrementing id after inserting data
it is often necessary to obtain the self increasing id of the inserted data during development. The underlying layer of mybatis will use jdbc to set the obtained id into the parameter object. The configuration is as follows:
<insert id="insert" parameterType="cn.hxzy.entity.Pet" keyProperty="id" useGeneratedKeys="true" >
After the insert statement is executed, the id of the entity is no longer empty.
keyProperty: indicates the property to save the returned id to the object
useGeneratedKeys: indicates that the primary key id is in self growth mode
practice:
1. Create the project fruit03, insert 100 fruit data into the database using the loop, and output the object id before and after insertion.
Reference answer:
mapper xml
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="cn.hxzy.entity.Fruit" useGeneratedKeys="true"> insert into fruit (`name`, color) values (#{name,jdbcType=VARCHAR}, #{color,jdbcType=VARCHAR}) </insert>
Test:
import cn.hxzy.entity.Fruit; import cn.hxzy.mapper.FruitMapper; 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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.Reader; import java.util.List; public class MainTest { SqlSession session; @Before public void getSession() throws IOException { Reader reader = Resources.getResourceAsReader("mybatis-conf.xml"); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); session = sessionFactory.openSession(true); reader.close(); } @Test public void add() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); for (int i = 0; i < 100; i++) { Fruit fruit = new Fruit(); fruit.setName("apple" + i); fruit.setColor("red"); mapper.insert(fruit); System.out.println(fruit.getId()); } } @After public void close() { session.close(); } }
9, Full map operation
sometimes during development, because the database structure often changes or developers do not create entities for diagram convenience, that is, map transmission is used for all attributes.
when using a map, you should replace all the original entity positions with a map. One object corresponds to one map.
interface modification:
import java.util.List; import java.util.Map; public interface PetMapper { int insert(Map map); List<Map> selectAll(); }
xml Transformation:
<insert id="insert" parameterType="map"> insert into pet(name, weight) values(#{name}, #{weight}) </insert> <select id="selectAll" resultType="map"> select * from pet </select>
Using map greatly affects the accuracy and readability of the program. Although this operation is not recommended by java programmers, many programmers still use it illegally.
practice:
1. Create the project fruit04, use the full map method to complete the basic operation of fruit, and use the unit test to judge the availability of the method.
Reference code:
mapper xml:
<?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="cn.hxzy.mapper.FruitMapper"> <sql id="Base_Column_List"> id, `name`, color </sql> <select id="selectAll" parameterType="java.lang.Integer" resultType="map"> select <include refid="Base_Column_List"/> from fruit </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from fruit where id = #{id,jdbcType=INTEGER} </delete> <insert id="insert" keyColumn="id" keyProperty="id" parameterType="map" useGeneratedKeys="true"> insert into fruit (`name`, color) values (#{name,jdbcType=VARCHAR}, #{color,jdbcType=VARCHAR}) </insert> <update id="updateByPrimaryKey" parameterType="map"> update fruit set `name` = #{name,jdbcType=VARCHAR}, color = #{color,jdbcType=VARCHAR} where id = #{id,jdbcType=INTEGER} </update> </mapper>
Interface:
import java.util.List; import java.util.Map; public interface FruitMapper { int deleteByPrimaryKey(Integer id); int insert(Map record); List<Map> selectAll(); int updateByPrimaryKey(Map record); }
Test:
import cn.hxzy.mapper.FruitMapper; 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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.Reader; import java.util.HashMap; import java.util.List; import java.util.Map; public class MainTest { SqlSession session; @Before public void getSession() throws IOException { Reader reader = Resources.getResourceAsReader("mybatis-conf.xml"); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); session = sessionFactory.openSession(true); reader.close(); } @Test public void add() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); Map fruit = new HashMap(); fruit.put("name", "apple"); fruit.put("color", "red"); mapper.insert(fruit); } @Test public void select() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); List<Map> fruits = mapper.selectAll(); System.out.println(fruits); } @Test public void delete() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); int i = mapper.deleteByPrimaryKey(1); System.out.println("Database impact:" + i); } @Test public void update() throws IOException { FruitMapper mapper = session.getMapper(FruitMapper.class); Map fruit = new HashMap(); fruit.put("id", 1); fruit.put("name", "apple"); fruit.put("color", "red"); mapper.insert(fruit); } @After public void close() { session.close(); } }