我们今天先来简单了解一下我们持久层框架, mybatis 的使用. 而且现在的注解成为趋势, 我主要说一下注解方向的使用吧(配置文件也会说)
从使用角度只要是三个部分, mybatis-config.xml,mapper.xml, 执行文件三个部分.
mybatis-config.xml:
主键标签为 configuration 成对出现的, 然后是 properties 也就是我们的配置, 用于配置数据库. settings 声明一些配置, 比如打印 sql 语句等, 后面会一个个去说. 然后就是我们的 mappers, 里面包含多个 mapper 标签, 也就是对应我们的 mapper.xml 文件, 在这里说一下一共有三种注入的方式, resource,class,url,resource 是通过 classpath 配置的, 如果你没有把 mapper 放置在 resources 配置下面, 需要在 maven 里设置编译, 不然我们的 mapper.xml 不会编译到 classpath 里, class 通过类来注入 mapper,url 一般是远程注入的. 再就是我们的 typehandlers, 可以指定类型转换的. 我们也可以继承 BaseTypeHandler 来重写父类的方法来自定义类型转换.
来一个我自己的简单配置.
<?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>
- <properties resource="app.properties">
- <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
- </properties>
- <settings>
- <!-- 打印查询语句 -->
- <setting name="logImpl" value="STDOUT_LOGGING"/>
- </settings>
- <environments default="${default.environment}">
- <environment id="dev">
- <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>
- <mapper resource="mybatis/dao/StudentMapper.xml"/>
- <!-- <mapper class="com.tuling.mybatis.dao.UserMapper"></mapper>-->
- <!-- <mapper url="mybatis.dao.StudentDao"></mapper>-->
- </mappers>
- </configuration>
配置还要很多, 后面源码解析里面会一点点来说明.
mapper.xml:
这个文件就是我们的编写 sql 的文件了, 里面主要标签就是 select,insert,update,delete 我们的增删改查标签, 再就是我们的缓存设置(二级缓存). 下次博客主要说博客, 源码级的.
select 里包含我们常见的 id,resultType,resultMap,id 用来指向我们的接口文件的类名, resultType 为我们 mybatis 自带的类型, 也可以是我们设置的对象 Bean,resultMap 是我们自己定义的返回类型. 这里可能会有疑问, 一堆多应该怎么来配置?
association 我们可以用他来指定一对多的配置, 同时可以配置懒查询还是及时查询的. 我们来看一个实例, 我们现有学生表格分数表, 学生对应很多科目的分数, 我们来看一下. 先来一段测试代码.
<?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/jdbc"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- </dataSource>
- </environment>
- </environments>
- <mappers>
- <!-- <mapper resource="mybatis/dao/StudentMapper.xml"/>-->
- <mapper class="mybatis.dao.StudentMapper"></mapper>
- <mapper class="mybatis.dao.ScoreMapper"></mapper>
- </mappers>
- </configuration>
- <?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="mybatis.dao.StudentMapper">
- <select id="selectUser" resultType="mybatis.bean.StudentBean">
- select * from stu where id = #{id}
- </select>
- </mapper>
- package mybatis.bean;
- import java.io.Serializable;
- public class StudentBean implements Serializable {
- private static final long serialVersionUID = 2193971369901198487L;
- private int id;
- private String name;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- @Override
- public String toString() {
- return "selectUser{" +
- "id=" + id +
- "name=" + name +
- '}';
- }
- }
- package mybatis;
- import mybatis.bean.ScoreBean;
- import mybatis.bean.StudentBean;
- import mybatis.dao.ScoreMapper;
- import mybatis.dao.StudentMapper;
- 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.Test;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.List;
- public class Test1 {
- @Test
- public void test() throws IOException {
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- SqlSession session = sqlSessionFactory.openSession();
- StudentMapper mapper = session.getMapper(StudentMapper.class);
- StudentBean result = mapper.selectUser(1);
- System.out.println(result);
- }
- }
这样我们查询到我们的学生信息, 但是还未包含我们的分数. 我们来改造一下.
<?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="mybatis.dao.StudentMapper">
- <resultMap id="studentMap" type="mybatis.bean.StudentBean">
- <id property="id" column="id"></id>
- <collection property="scoreBean" ofType="mybatis.bean.ScoreBean">
- <id property="id" column="sid"></id>
- <!-- <result property="subject" column="subject"></result>-->
- <result property="score" column="score"></result>
- <result property="studentId" column="studentId"></result>
- </collection>
- </resultMap>
- <select id="selectUser" resultMap="studentMap">
- select t.id,t.name,t.address,t.num,s.id as sid,s.subject,s.score,s.studentId as studentId from student t left join score s on s.studentId = t.id where t.id = #{id}
- </select>
- </mapper>
这样就可以查询到对应关系了. 需要注意的事子表如果和主表重名, 一定给子表起一个别名, 而且子表的每一项需要写 result, 不然没有结果的, 但是还不是很好, 本来是一个对象一个集合, 现在直接变成集合了, 我们再来改改.
<?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="mybatis.dao.StudentMapper">
- <resultMap id="studentMap" type="mybatis.bean.StudentBean">
- <id property="id" column="id"></id>
- <collection property="scoreBean" javaType="java.util.ArrayList" ofType="mybatis.bean.ScoreBean" select="mybatis.dao.ScoreMapper.selectScoreByStudentId" column="{studentId=id}">
- </collection>
- </resultMap>
- <select id="selectUser" resultMap="studentMap">
- select * from student t where t.id = #{id}
- </select>
- </mapper>
这个比较好用, 但是切记, 不是懒加载, 不是懒加载, 需要注意的是 collection 的 property 指定我们实体类 Bean 类中集合的名字. ofType 是指向我们一对多中多方的实体 Bean,select 指定我们对应的第二句 sql 语句, 也就是我们的子查询语句.
column="{studentId=id}" 中 studentId 是我们的子查询参数名, id 是和我们主表的对应关系. 就是说, 我们要子表的什么参数等于我们的主表的哪个参数传递过去.
接下来就是我们简单的一对一了 (也可以当做一对多, 但是没啥卵用的多对一, 项目经理让从多往一查的时候, 请你吐他...) 我们来看我一下我的配置
<?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="mybatis.dao.ScoreMapper">
- <resultMap id="scoreMap" type="mybatis.bean.ScoreBean">
- <id property="id" column="id"></id>
- <result property="subject" column="subject"></result>
- <result property="score" column="score"></result>
- <association property="studentBean" javaType="mybatis.bean.StudentBean" column="studentId">
- <id property="id" column="id"></id>
- <result property="name" column="name"></result>
- <result property="address" column="address"></result>
- <result property="num" column="num"></result>
- </association>
- </resultMap>
- <select id="selectScoreByStudentId" resultMap="scoreMap">
- select * from score s left join student t on s.studentId = t.id where studentId = #{studentId}
- </select>
- </mapper>
这个比较简单, 就不说了, 就是写了一个 resultMap. 我们来看一下两条 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="mybatis.dao.ScoreMapper">
- <resultMap id="scoreMap" type="mybatis.bean.ScoreBean">
- <id property="id" column="id"></id>
- <result property="subject" column="subject"></result>
- <result property="score" column="score"></result>
- <association property="studentBean" javaType="mybatis.bean.StudentBean" select="mybatis.dao.StudentMapper.selectUser" column="studentId">
- <id property="id" column="id"></id>
- <result property="name" column="name"></result>
- <result property="address" column="address"></result>
- <result property="num" column="num"></result>
- </association>
- </resultMap>
- <select id="selectScoreByStudentId" resultMap="scoreMap">
- select * from score where studentId = #{studentId}
- </select>
- </mapper>
简单解释一下, 其实和上面 collection 差不多的, select 指定查询 sql 位置, column 执行传递过去的参数.
其余的 insert,update,delete 都差不多, 我这里就放在一起说了.
id | 命名空间中的唯一标识符,可被用来代表这条语句。 |
parameterType | 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器推断出具体传入语句的参数,默认值为未设置(unset)。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:true(对于 insert、update 和 delete 语句)。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖驱动)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认值:未设置(unset )。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
keyColumn | (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。 |
useGeneratedKeys="true" 这个相当来说配置的还是比较多的, 也就是我们新增成功后, 我们的对象可以返回我们插入成功的主键 ID.
拼装 sql:
- #{}: 是预处理, 也是一个占位符的方式来执行 sql,${}是 sql 的拼接, 我们其实可以这样来写.
- @Select("select * from ${}_sys_log where id=#{condition}")
- public SystemLog findSystemLog(String year,String condition);
也就是说, 我们对日志 sys_log 表做了分库分表, 按照年份来区分的表, 这时我们可以采用 sql 拼接的方式来做.
但尽力不要用拼接的方式来做, 后面我将动态 sql 会说具体怎么来实现.${}容易被 sql 注入. 所以我们尽力还用占位符的方式来处理我们的 SQL.
然后就是我们的插件集成, 还有缓存, 下次博客我们来说说缓存吧.
忘记了, 学 mybatis 的使用, 推荐一个网站 https://mybatis.org/mybatis-3/zh/index.html 上面挺全的(没有源码解析, 源码还得回来看我博客).
来源: https://www.cnblogs.com/cxiaocai/p/11520734.html