Mybatis轻量级ORM框架

简介

Mybatis是一个轻量级的ORM框架,自定义 SQL,几乎免除所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。极大简化持久层的操作。

Mybatis使用

要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。POM或build path。

在这里插入图片描述
基于XML文件创建SqlSessionFactory对象:

<--mybatis-config.xml-->
<?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="mybatis.properties"></properties>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>
# mybatis.properties:
driver=
url=
username=
password=

properties注解用于读取properties文件,mybatis支持表达式变量${},#{}直接赋值,当然可以直接再xml中写入。

代码构建SqlSessionlFactory

String resource="mybatis-config.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);

SqlSessionFactory是应用级的,而SqlSession是线程级的即每产生一个操作数据库的线程都要构造一个SqlSession。

<?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="bolen.example.dao.UserMapper">
    <select id="selectAll" resultType="bolen.example.pojo.User">
        select * from user
    </select>


</mapper>

基于SqlSession创建查询对象:

SqlSession sqlSession=sqlSessionFactory.openSession();
List<User> list=sqlSession.selectList("bolen.example.dao.UserMapper.selectAll");
System.out.println(list);

SqlSession对象方法的参数基于mapper配置文件的namespace属性和id属性唯一确定。

mapper代理开发

Mybatis配置文件结构

在这里插入图片描述

<?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属性-->
    <properties resource="mybatis.properties"></properties>
    
    <!--设置-->
    <settings>
        <setting name="" value=""/>
    </settings>
    
    <!--类型别名,用于简写类的全限定名-->
    <typeAliases></typeAliases>
    
    <!--类型处理器-->
    <typeHandlers></typeHandlers>
    
    <!--顺序工厂-->
    <objectFactory type=""></objectFactory>
    
    <!--插件-->
    <plugins>
        <plugin interceptor=""></plugin>
    </plugins>
    
    <!--数据源环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <!--数据厂商标识-->
    <databaseIdProvider type=""></databaseIdProvider>
    
    <!--映射器-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

顺序不能变。

类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。见下面的例子:

@Alias("author")
public class Author {
    ...
}

映射器(mappers)
MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。

可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

XML映射结构

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

insert,update,delete

<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

<update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

在这里插入图片描述

select查询语句是 MyBatis 中最常用的元素之一

<select id="selectPerson" parameterType="int" resultType="hashmap">
  SELECT * FROM PERSON WHERE ID = #{id}
</select>
<!--#{}用来传递动态参数-->

SELECT的属性

<select
  id="selectPerson"
  parameterType="int"
  parameterMap="deprecated"
  resultType="hashmap"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">

在这里插入图片描述

动态sql

Java API

使用XML文件是配置环境environments,如果你调用了接受 properties 实例的方法,那么 MyBatis 就会加载这些属性,并在配置中提供使用。绝大多数场合下,可以用 ${propName} 形式引用这些配置值。

String resource = "org/mybatis/builder/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);

Resources 工具类,这个类在 org.apache.ibatis.io 包中:

SqlSessionFactory的创建:

URL getResourceURL(String resource)
URL getResourceURL(ClassLoader loader, String resource)
InputStream getResourceAsStream(String resource)
InputStream getResourceAsStream(ClassLoader loader, String resource)
Properties getResourceAsProperties(String resource)
Properties getResourceAsProperties(ClassLoader loader, String resource)
Reader getResourceAsReader(String resource)
Reader getResourceAsReader(ClassLoader loader, String resource)
File getResourceAsFile(String resource)
File getResourceAsFile(ClassLoader loader, String resource)
InputStream getUrlAsStream(String urlString)
Reader getUrlAsReader(String urlString)
Properties getUrlAsProperties(String urlString)
Class classForName(String className)

SqlSession创建:
SqlSessionFactory 有六个方法创建 SqlSession 实例。通常来说,当你选择其中一个方法时,你需要考虑以下几点:

  • 事务处理:希望在 session 作用域中使用事务作用域,还是使用自动提交还是手动提交。
  • 数据库连接:MyBatis 帮助从已配置的数据源获取连接,还是使用自己提供的连接。
  • 语句执行: MyBatis 复用 PreparedStatement 和/或批量更新语句。

默认的 openSession() 方法没有参数,它会创建具备如下特性的 SqlSession:

  • 事务作用域将会开启(也就是不自动提交)。
  • 将由当前环境配置的 DataSource 实例中获取 Connection 对象。
  • 事务隔离级别将会使用驱动或数据源的默认设置。
  • 预处理语句不会被复用,也不会批量处理更新。

传参问题

顺序传递参数


User selectUser(String name, int deptId);
<select id="selectUser" resultType="com.wyj.entity.po.User">
	select * from user where userName = #{0} and deptId = #{1}
</select>

注意:里面的数字代表你传入参数的顺序,不是特别建议使用这种方法传递参数,特别是参数个数多的时候

注解@Param传递参数

User selectUser(@Param("userName") String name, int @Param("deptId") id);
<select id="selectUser" resultType="com.wyj.entity.po.User">
	select * from user where userName = #{userName} and deptId = #{deptId}
</select>

使用Map集合传递参数

User selectUser(Map<String, Object> params);
<select id="selectUser" parameterType="java.util.Map" resultType="com.wyj.entity.po.User">
	select * from user where userName = #{userName} and deptId = #{deptId}
</select>

使用parameterType限定传入的参数类型,会自动按key同名赋值

使用JavaBean实体类传递参数

User selectUser(User user);
<select id="selectUser" parameterType="com.wyj.entity.po.User" resultType="com.wyj.entity.po.User">
	select * from user where userName = #{userName} and deptId = #{deptId}
</select>

传入的为Java Bean,自动根据成员变量名进行赋值。

XML的mapper代码开发

xml结构:

在这里插入图片描述
select语句有很多属性:
在这里插入图片描述
在这里插入图片描述

其中最主要的是:
在这里插入图片描述

resultMap结果集映射:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
最主要的是result用于映射Java对象和数据库表。property属性绑定Brand对象的成员变量,column绑定数据库表字段,其他属性用于绑定数据类型。
在这里插入图片描述

insert同样也有很多属性:
在这里插入图片描述

insert,delete,update只有返回影响的行数没有resultMap

总结:
在这里插入图片描述

动态sql
在条件查询是常常要使用动态查询
动态sql
mybatis中文文档

注解开发

最初设计时,MyBatis是一个XML驱动的框架。配置信息是基于XML的,而且映射语句也是定义在XML中的。而到了MyBatis3,有新的选择了:利用注解实现SQL的映射。MyBatis3构建在全面而且强大的Java 注解(Java annotation)之上。注解提供了一种便捷的方式来实现简单SQL映射语句,可以简化编写XML的过程。
http://www.mybatis.cn/archives/678.html

常用注解分为三大类:SQL语句映射,结果集映射和关系映射。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在org.apache.ibatis.annotations包下包含了mybatis所有注解。
http://www.mybatis.org/mybatis-3/zh/java-api.html

@CacheNamespace相当于cache标签和mapper是同级别的,@CacheNamespace,作用于mapper接口上面,是用来实现二级缓存的。
@Property相当于property标签,用于初始化参数。

<properties resource="config.properties">
<!--值会被config.properties中的值所覆盖 -->
  	<property name="username" value="root"/>
   	<property name="password" value="0000"/>
</properties>

@Select@Insert@Update,@Delete是sql语句映射注解,使用注解不需要再xml文件中注入sql语句。
BrandMapper.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="bolen.example.dao.BrandMapper">

</mapper>

注解映射sql语句:


public interface BrandMapper {
    @Select("select * from brand")
    List<Brand> selectAll();
}

依然通过${}#{}传递参数。该四个注解只用于简单的sql语句的映射。

@InsertProvider@DeleteProvider@UpdateProvider@SelectProvider,分别对应着sql中的增删改查四种操作。是前四个的升级版。

public interface UserMapper 
{
    @SelectProvider(type = SqlProvider.class, method = "selectUser")
    User getUser(long userId);
}

@SelectProvider注解用于生成查询用的sql语句,有别于@Select注解,@SelectProvide指定一个Class及其方法,并且通过调用Class上的这个方法来获得sql语句。在我们这个例子中,获取查询sql的方法是SqlProvider.selectUser。

@SelectProvide中type参数指定的Class类,必须要能够通过无参的构造函数来初始化。

@SelectProvide中method参数指定的方法,必须是public的,返回值必须为String。

public class SqlProvider 
{
    public String selectUser(long userId) 
    {
      return "select * from user where userId=" + userId;
    }
}

参数问题
通过注解声明的方法,在注解方法中传递参数,当有多个参数时用@Param传递参数。如果使用了@Param注解的话,那么相应sql映射方法必须接受Map<String, Object>做为参数:

public String selectUser2(Map<String, Object> para) 
{
    return "select * from user where userId=" + para.get("userId");
}
@SelectProvider(type = SqlProvider.class, method = "selectUser2")
public User getUser2(@Param("userId") long userId);

在超过一个参数的情况下,@SelectProvide方法必须接受Map<String, Object>做为参数。其他三个用法一致。

@Result@Results@ResultMap是结果集映射的三大注解。

持久层通常遇到的问题时Java Bean于数据库的字段不一致或数据类不一致的问题,如Bean中brandId,字段为brand_id。结果三大注解有效的解决了这些问题。

声明结果集映射关系代码:

@Select({"select id, name, class_id from student"})
@Results(id="studentMap", value={
    @Result(column="id", property="id", jdbcType=JdbcType.INTEGER, id=true),
    @Result(column="name", property="name", jdbcType=JdbcType.VARCHAR),
    @Result(column="class_id ", property="classId", jdbcType=JdbcType.INTEGER)
})
List<Student> selectAll();

引用结果集代码:

@Select({"select id, name, class_id from student where id = #{id}"})
@ResultMap(value="studentMap")
Student selectById(integer id);

@Results各个属性的含义,id为当前结果集声明唯一标识,value值为结果集映射关系。
@Result代表一个字段的映射关系,column指定数据库字段的名称,property指定实体类属性的名称,jdbcType数据库字段类型,@Result里的id值为true表明主键,默认false。
@ResultMap来引用映射结果集,其中value可省略。

当表字段与成员变量不对应时查询不到数据:
在这里插入图片描述
结果集注解实现了resultMap标签的功能:

@Select("select * from brand")
@Result(column = "brand_id",property = "id", jdbcType = JdbcType.INTEGER, id = true)
@Result(column = "brand_name",property = "brandName", jdbcType = JdbcType.VARCHAR)
@Result(column = "company_name", property = "companyName", jdbcType = JdbcType.VARCHAR)
List<Brand> selectAll();

在这里插入图片描述
@Result注解只能本次使用,之后的查询仍然要重写,使用@Results后可以直接使用@Result注解引用,其有id和value属性,value时代码块{}

@Select("slelct * from brand")
  @Results(id = "brandMapper",value = {
          @Result(column = "brand_id",property = "id", jdbcType = JdbcType.INTEGER, id = true),
          @Result(column = "brand_name",property = "brandName", jdbcType = JdbcType.VARCHAR),
          @Result(column = "company_name", property = "companyName", jdbcType = JdbcType.VARCHAR)
  })
  List<Brand> selectAllThree();


//之后可以直接通过@ResultMap引用
@ResultMap(value="brandMappper")

使用@Results注解必须使用@Result注解,使用@Results注解后的ip属性可以被@ResultMap注解再其他地方引用,简化@Result的书写。区别在于@Results实现数据表到Java Bean的封装可以重复利用,@Result实现数据项(字段)到Bean的成员变量的映射局部疯转。

@one注解用于一对一关系映射

@Select("select * from student")  
@Results({  
    @Result(id=true,property="id",column="id"),  
    @Result(property="name",column="name"),  
    @Result(property="age",column="age"),  
    @Result(property="address",column="address_id",one=@One(select="cn.mybatis.mydemo.mappers.AddressMapper.getAddress"))  
})  
public List<Student> getAllStudents();  

@many注解用于一对多关系映射

@Select("select * from t_class where id=#{id}")  
@Results({  
    @Result(id=true,column="id",property="id"),  
    @Result(column="class_name",property="className"),  
    @Result(property="students", column="id", many=@Many(select="cn.mybatis.mydemo.mappers.StudentMapper.getStudentsByClassId"))  
    })  
public Class getClass(int id); 

@Options注解能够设置缓存时间,能够为对象生成自增的key。
在这里插入图片描述

@Select("select * from brand where brand_id = #{id}}")
@Options(useCache = true,flushCache = Options.FlushCachePolicy.FALSE,timeout = 10000)
@ResultMap(value = "brandMapper")
Brand selectByIdOne(@Param("id") int id);

配合查询语句使用,主要是开关一些查询的选项。比如useCache = true表示将会缓存本次查询结果,以提高下次查询速度;flushCache = Options.FlushCachePolicy.FALSE表示查询时不刷新缓存;timeout = 10000表示查询结果缓存10000秒。

@Insert({
        "insert into login_ticket(user_id,ticket,status,expired) ",//每句sql语句后面加一个空格
        "values(#{userId},#{ticket},#{status},#{expired})"
})
@Options(useGeneratedKeys = true, keyProperty = "id",keyColumn="brand_id")   //自动生成主键并将生成的值注入给属性id
int insertLoginTicket(LoginTicket loginTicket);

@Options属性userGeneratedKeys的值为true,并指定实例对象中主键的属性名keyProperty以及在数据库中的字段名keyColumn。这样在插入数据后,id属性会被自动赋值。

@SelectKey用于向数据库中插入一条数据,同时有希望返回该条记录的主键。http://www.mybatis.cn/archives/741.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xvwen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值