根据 MyBatis官方文档 的介绍:
- MyBatis是围绕着
SqlSessionFactory
的实例来展开的。 - 实例
SqlSessionFactory
可以由SqlSessionFactoryBuilder
来创建。 - 而
SqlSessionFactoryBuilder
则可以由一个XML配置文件来创建。
(更准确的讲,是由这个XML文件内容构成的InputStream来创建。)
假设我们这个XML配置文件叫做 mybatis-config.xml
,并假设它被放置在了相应的resource文件夹下,则创建 SqlSessionFactory
的方式为:
String resource = "<file_dir>/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
而这个 mybatis-config.xml
文件包含了关于db的重要配置信息,如数据源的连接设置,以及 mapper 的配置(后面会讲到)。
<?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"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://<url>:<port_e.g._3306>/<db_name>"></property>
<property name="username" value="<user_name>"></property>
<property name="password" value="<pwd>"></property>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="ProjectMapper.xml"></mapper>
</mappers>
</configuration>
这里结尾处的
<mappers>
<mapper resource="ProjectMapper.xml"></mapper>
</mappers>
即是后面会讲到的mapper映射配置信息。
有了 SqlSessionFactory
,那么MyBatis就可以开工干活了。MyBatis最重要的工作,就是通过半自动化的框架来执行SQL语句。所以我们可以直切主题,看如何执行一条关于上面配置的db的一条SQL语句。
可以使用 SqlSessionFactory
来获得一个 SqlSession
,即一个sql会话,通过它来调用SQL语句。
此时需要解决的两个问题:
- 这个SQL语句应该写在哪里?
- 这个SQL语句查询出来的对象,应该放在什么样的Java对象里?
后一个问题相对容易,可直接创建一个 PmProject
的entity来作为Java bean:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PmProject implements Serializable {
private Integer id;
private String uuid;
private String name;
@Override
public String toString() {
return "PmProject{" +
"id=" + id +
", uuid='" + uuid + '\'' +
", name='" + name + '\'' +
'}';
}
}
这里使用了lombok注解来简化类似于getter/setter模板函数的设置。
下一个问题是,SQL放在哪里?嗯,这就和之前在 mybatis-config.xml
中结尾处的mapper文件结合起来了。即,在那里设置的mapper文件,就是用于告知MyBatis,自己将要执行的SQL放在哪里,即映射为SQL的语句位置。
创建mapper文件,用于放置将要执行的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="com.terencexie.springcloud.PmProjectMapper">
<select id="selectProject" resultType="com.terencexie.springcloud.entities.PmProject">
SELECT * FROM pm_project WHERE id = #{id}
</select>
</mapper>
可以看到在 com.terencexie.springcloud.PmProjectMapper
这个名称空间下,创建了一个标识为 selectProject
的SQL语句。这条语句的返回结果,被放在之前创建的 PmProject
这个Java bean中。而在具体的SQL语句中有一个 #{id}
作为查询参数。
有了 SqlSession
,也有了放置执行SQL语句的位置,那么便可以将上面的所有元素结合起来,给出一个粗糙demo:
public class MyBatisTest {
private static SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
try (SqlSession openSession = sqlSessionFactory.openSession()) {
PmProject pmProject =
openSession.selectOne("com.terencexie.springcloud.PmProjectMapper.selectProject"
, 1);
System.out.println(">>>>>>>>> [T]" + pmProject);
}
}
}
注意这里使用获取到的 SqlSession
时,指定了SQL的具体位置 com.terencexie.springcloud.PmProjectMapper.selectProject
,它有mapper文件中的namespace com.terencexie.springcloud.PmProjectMapper
和其中的唯一标识符 selectProject
组合而成。
后面跟随的一个参数 1
,就是在mapper文件中的SQL语句里用到的 #{id}
参数。
如此,便将db中的一条信息通过MyBatis加载到Java bean中了。
这种方式比较适合iBatis的用户,但弊端也很明显,就是查询时没有类型检查。比如这里需要传递的参数id需要是整型,但你传递字符串也能通过(因为 selectOne()
方法接受Object类型)。所以在MyBatis中更推荐的是按照上面的思想,提供一个Mapper接口,通过这个接口来实现查询。
例如可创建一个 PmProjectMapper
接口:
package com.terencexie.springcloud.mapper;
import com.terencexie.springcloud.entities.PmProject;
public interface PmProjectMapper {
PmProject getById(Integer id);
}
此时,在根据这个接口的信息来修改之前的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="com.terencexie.springcloud.mapper.PmProjectMapper">
<select id="getById" resultType="com.terencexie.springcloud.entities.PmProject">
SELECT * FROM pm_project WHERE id = #{id}
</select>
</mapper>
注意到,这里的namespace就是 PmProjectMapper
接口的包路径类名,而SQL的唯一识别号,则使用的是这个 PmProjectMapper
接口中的方法名 getById
。
如此,通过MyBatis来连通db的方式就变成了:
public class MyBatisTest {
private static SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
try (SqlSession openSession = sqlSessionFactory.openSession()) {
PmProjectMapper projectMapper = openSession.getMapper(PmProjectMapper.class);
PmProject pmProject = projectMapper.getById(1);
System.out.println(">>>>>>>>> [T]" + pmProject);
}
}
}