MyBatis核心之实践初体验
一、MyBatis搭建开发环境
首先我们需要在Maven项目中引入依赖坐标,包括MyBatis核心依赖、Junit测试依赖、MySQL数据库依赖以及日志log4j依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.1</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
|
然后,我们需要引入日志配置文件log4j.xml
,可以方便我们观察MyBatis的运行时信息,帮助我们理解MyBatis的运行原理,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Encoding" value="UTF-8" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout> </appender> <logger name="java.sql"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="info" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>
|
其次,我们需要编写MyBatis的核心配置文件,这是MyBatis实践中最重要的一环,其大致内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="jdbc.properties"/> <typeAliases> <package name="com.huling.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <package name="com.huling.mapper"/> </mappers> </configuration>
|
上述配置文件中引入了数据源连接的配置文件jdbc.properties
,其内容如下:
1 2 3 4
| jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true jdbc.username=root jdbc.password=root
|
接着,我们还需要建立项目的源代码目录结构如实体类包com.huling.pojo
、数据持久层包com.huling.mapper
等,整体项目的结构如下图:
其中,实体类User
关联数据库中的t_user
表,对象属性与数据表字段一一对应:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| package com.huling.pojo;
public class User { private Integer id; private String username; private String password; private Integer age; private String sex; private String email;
public User() { }
public User(Integer id, String username, String password, Integer age, String sex, String email) { this.id = id; this.username = username; this.password = password; this.age = age; this.sex = sex; this.email = email; }
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getSex() { return sex; }
public void setSex(String sex) { this.sex = sex; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", email='" + email + '\'' + '}'; } }
|
最后,我们需要建立数据持久层的接口UserMapper
及其对应的XML映射文件UserMapper.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.huling.mapper;
import com.huling.pojo.User;
public interface UserMapper { int insertSimpleUser();
int updateSimpleUser();
int deleteSimpleUser();
User getSimpleUser();
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.huling.mapper.UserMapper"> <insert id="insertSimpleUser"> insert into t_user values (null,'tom','123456',22,'男','tom@163.com') </insert>
<update id="updateSimpleUser"> update t_user set username = 'admin' where id = 3 </update>
<delete id="deleteSimpleUser"> delete from t_user where id = 3 </delete>
<select id="getSimpleUser" resultType="user"> select * from t_user where id = 2 </select> </mapper>
|
二、MyBatis搭建测试环境
通过单元测试Junit技术,我们可以方便地测试MyBatis的各项功能,下面是一个简单的测试程序代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class MyBatisTest {
@Test public void test1() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession(true)) { UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.getSimpleUser(); System.out.println("user = " + user); } }
}
|
对象属性与数据库的表字段直接如何映射转换的呢,我们先做一个实验,给实体类User的构造方法和Getter、Setter方法添加打印信息,看一看会发生什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| package com.huling.pojo;
public class User { private Integer id; private String username; private String password; private Integer age; private String sex; private String email;
public User() { System.out.println("User.User无参构造"); }
public User(Integer id, String username, String password, Integer age, String sex, String email) { System.out.println("User.User有参构造"); this.id = id; this.username = username; this.password = password; this.age = age; this.sex = sex; this.email = email; }
public Integer getId() { System.out.println("User.getId"); return id; }
public void setId(Integer id) { System.out.println("User.setId:" + id); this.id = id; }
public String getUsername() { System.out.println("User.getUsername"); return username; }
public void setUsername(String username) { System.out.println("User.setUsername:" + username); this.username = username; }
public String getPassword() { System.out.println("User.getPassword"); return password; }
public void setPassword(String password) { System.out.println("User.setPassword:" + password); this.password = password; }
public Integer getAge() { System.out.println("User.getAge"); return age; }
public void setAge(Integer age) { System.out.println("User.setAge:" + age); this.age = age; }
public String getSex() { System.out.println("User.getSex"); return sex; }
public void setSex(String sex) { System.out.println("User.setSex:" + sex); this.sex = sex; }
public String getEmail() { System.out.println("User.getEmail"); return email; }
public void setEmail(String email) { System.out.println("User.setEmail:" + email); this.email = email; }
@Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", email='" + email + '\'' + '}'; } }
|
因此可以发现,默认从查询的行记录转换为Java对象的情况下,对于对象属性与表字段一致时,直接通过对象的Setter方法注入属性值,而对象也是先通过无参构造函数创建的实例。
其实与上面的情况相对应,当我们的方法参数中包含Java对象时,也需要通过Getter方法取出对象的属性值,下面添加一个新的Mapper测试接口方法,观察一下会发生什么?
1 2 3 4 5 6 7 8 9 10
| int insertUser(User user);
<insert id="insertUser"> insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email}) </insert>
int result = mapper.insertUser(new User(null,"test","test",12,"女","mail"));
|