Mybatis02:CRUD操做及配置解析

使用代理对象的方式实现CRUD操做

select

  • select标签是mybatis中经常使用的查询标签
  • select中有不少属性能够详细配置每一条SQL语句
    • id属性:标识是咱们接口中的那个方法。接口中的方法名与映射文件中的SQL语句id一一对应
    • parameterType属性:用于指定传入的参数类型
    • resultType属性:用于指定结果集的类型
    • ......

需求:根据id查询用户java

一、在UserDao中添加对应方法mysql

/**
     * 根据用户id查询用户
     * @param userId 要查询的用户id
     * @return 若是存在返回该用户,不存在则返回null
     */
    User findById(Integer userId);

二、在UserDao.xml中添加select语句sql

<!--根据id查询用户(记住这里有返回值类型,要告知程序返回值类型是什么)-->
    <select id="findById" resultType="com.lng.pojo.User">
        select * from user where id = #{id};
    </select>

三、在测试类中测试
这里和下面就不测试了,就是获取SqlSession对象来进行操做数据库

查询使用聚合函数缓存

一、在UserDao中添加对应方法服务器

/**
     * 查询总用户数
     * @return
     */
    int findTotal();

二、在UserDao.xml中添加对应的语句mybatis

<!--查询总用户数-->
    <select id="findTotal" resultType="int">
        select count(*) from user;
    </select>

有多个查询条件(多是同一个对象的,也可能不是同一个对象的)
例如根据用户名和地址查询用户并发

思路一:直接在方法中传递参数
一、在接口方法的参数前加@Param属性
二、Sql语句编写的时候,直接取@Param中设置的值便可,不须要单独设置参数类型app

//在UserDao接口中添加以下方法
User findByAddAndName(@Param("username") String username, @Param("address") String address);

//在UserDao.xml中添加以下语句
<select id="findByAddAndName" resultType="com.lng.pojo.User">
        select * from user where username = #{username} and address = #{address};
</select>

思路二:使用Map
一、在接口方法中,参数直接传递Map函数

User findByAddAndName(Map<String, Object> map);

<select id="findByIdAndName" resultType="com.lng.pojo.User" parameterType="map" >
        select * from user where address = #{address} and username = #{username};
</select>

思路三:自定义一个查询类
其实这种方式和思路二是一个意思,就是将咱们要查询的条件封装进一个类中,而后当成参数给传递过去

总结:若是参数较多的状况下建议使用Map或自定义实现类的方式,反之则使用直接传递参数的方式

注意事项

在使用增、删、改操做须要提交事务

一开始执行的时候就将自动提交事务给关闭了,因此要咱们手动提交事务,使用sqlSession.commit()提交

insert

咱们使用insert标签进行插入操做,他的配置和select差很少

给数据库增长一个用户

一、在UserDao接口中添加对应方法

/**
     * 保存方法
     * @param user
     */
    void saveUser(User user);

二、在UserDao.xml中添加对应语句

<!--保存用户-->
    <insert id="saveUser" parameterType="com.lng.pojo.User">
        <!--配置插入操做后,获取插入数据的id,会自动填充至咱们的User对象中-->
        <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="java.lang.Integer">
            select last_insert_id();
        </selectKey>
        insert into user (username, birthday, sex, address) values (#{username}, #{birthday}, #{sex}, #{address});
     </insert>

update

使用update标签进行用户的更新

修改用户信息

一、编写接口方法

/**
     * 更新操做
     * @param user
     */
    void updateUser(User user);

二、编写对应的配置文件SQL

<!--更新用户-->
    <update id="updateUser" parameterType="com.lng.pojo.User">
        update user set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address}
        where id = #{id};
    </update>

delete

可使用delete标签进行删除操做。

删除用户

一、编写对应接口方法

/**
     * 根据id删除用户
     * @param userId 须要被删除的用户的id号
     */
    void deleteUser(Integer userId);

二、编写对应配置文件的SQL

<!--删除用户-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{id}; <!--若是参数是基本数据类型及其包装类,那么里面的占位符名随便写-->
    </delete>

模糊查询

在java代码中添加sql通配符(经常使用)

/**
     * 根据名称模糊查询用户名称
     * @param username
     * @return
     */
    List<User> findByName(String username);

    List<User> users = mapper.findByName("%王%");

<!--对应配置文件的写法-->
 <!--根据名称模糊查询的语法-->
    <select id="findByName" resultType="com.lng.pojo.User" parameterType="java.lang.String">
        select * from user where username like #{username};<!--这种方式使用的是占位符的方式,因此在传递参数的时候要直接传递完整的模糊语句-->
    </select>
  • 执行的SQL

在sql语句中拼接通配符,会引发SQL注入等问题

/**
     * 根据名称模糊查询用户名称
     * @param username
     * @return
     */
    List<User> findByName(String username);

    List<User> users = mapper.findByName("王");

<!--在对应中配置文件中编写-->
 <!--根据名称模糊查询的语法-->
    <select id="findByName" resultType="com.lng.pojo.User" parameterType="java.lang.String">
       <!-- select * from user where username like '%${value}%'; 这种方式了解就好了,基本不会使用,这种方式不是用预处理SQL的方式-->
    </select>
  • 执行的SQL

  • 注意事项:咱们将原来的#{}占位符,改为了\({value}。注意若是用模糊查询的这种写法,那么\){value}的写法就是固定的,不能改为其它名字。这个${value}就是咱们传递的参数。

  • #{}与${}的区别

    • #{}表示一个占位符:经过#{}能够实现PreparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}能够有效防止sql注入。#{}能够接收简单类型值或pojo属性值。若是parameterType传输单个简单类型值,#{}括号中能够是value或其余名称

    • \({}表示拼接sql串:经过\){}能够将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,\({}能够接收简单类型值或pojo属性值,若是parameterType传输单个简单类型值,\){}括号中只能是value

      • 模糊查询的${value}源码分析

配置解析

核心配置文件

  • SqlMapConfig.xml核心配置文件
  • Mybatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息
  • 能配置的内容以下:

environments元素

<environments default="development">
 <environment id="development">
   <transactionManager type="JDBC">
     <property name="..." value="..."/>
   </transactionManager>
   <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>
  • 配置Mybatis的多套运行环境,将SQL映射到多个不一样的数据库上,必须指定其中一个为默认的运行环境(经过default指定)
  • 子元素节点:environment
    • dataSource元素使用标准的JDBC数据源接口来配置JDBC链接对象的资源
    • 数据源(dataSource)是必须配置的
    • 有三种内建的数据源类型:type="[UNPOOLED|POOLED|JNDI]")
    • unpooled:这个数据源的实现只是每次被请求是打开和关闭链接(没有使用数据库链接池技术)
    • pooled:这种数据源的实现利用“池”的概念将JDBC链接对象组织起来,这是一种使得并发Web应用快速响应请求的流行处理方式
    • jndi:这个数据源的实现是为了能在如Spring或应用服务器这类容器中使用,容器能够集中或在外部配置数据源,而后放置一个JNDI上下文引用。
    • 数据源也有不少第三方的实现:好比DBCP、c3p0、druid等等...
    • 子元素节点:transactionManager-[事务管理器]:
<!-- 语法 -->
<transactionManager type="[ JDBC | MANAGED ]"/>

mappers元素
mappers

  • 映射器:定义映射SQL语句文件的位置
  • 既然Mybatis的行为其余元素已经配置完了,咱们先就要定义SQL映射语句。可是首先咱们须要告诉Mybatis到哪里去找到这些语句。Java在自动查找这方面没有提供一个很好的方法,因此最佳的方式是告诉Mybatis到哪里去找映射文件。你可使用相对于类路径的资源引用,或彻底限定资源定位符(包括file:///的URL),或类名和报名等。映射器是Mybatis中最核心的组件之一,在Mybatis3以前,只支持xml映射器,即:全部的SQL语句都必须在xml文件中配置。而从Mybatis3开始,还支持接口映射器,这种映射器方式容许Java代码的方式注解定义SQL语句,很是简洁。

引入资源的方式

<!-- 使用相对于类路径的资源引用 -->
<mappers>
 <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用彻底限定资源定位符(URL) -->
<mappers>
 <mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<!--
使用映射器接口实现类的彻底限定类名
须要配置文件名称和接口名称一致,而且位于同一目录下
-->
<mappers>
 <mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!--
将包内的映射器接口实现所有注册为映射器
可是须要配置文件名称和接口名称一致,而且位于同一目录下
-->
<mappers>
 <package name="org.mybatis.builder"/>
</mappers>

Mapper文件

<?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.kuang.mapper.UserMapper">
   
</mapper>
  • namespace中文意思:名称空间,做用以下
    • namespace的命名必须跟某个接口的同名
    • 接口中的方法与映射文件中SQL语句id应该一一对应
    • namespace和子元素的id联合保证惟一性,区别不一样的mapper
    • 绑定DAO接口
    • namespace命名规则:包名+类名

Properties优化

数据库这些属性都是可外部配置且可动态替换的,既能够在典型的Java属性文件中配置,亦可经过properties元素的子元素来传递。
一、在资源目录下新建一个JdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=123456

二、将文件导入properties配置文件

<configuration>
   <!--导入properties文件-->
   <properties resource="JdbcConfig.properties"/>

   <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>
       <mapper resource="mapper/UserMapper.xml"/>
   </mappers>
</configuration>

typeAliases优化

类型别名视为Java类型设置一个短的名。他只和XML配置有关,存在的意义仅在于用来减小全类名书写的冗余

<!--使用typeAliases用于配置别名。-->
    <typeAliases>
        <!--typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就再也不区分大小写
            (再也不区分大小写的的意思是下面引用别名的时候能够是user, USER, UsEr等都是能够的)
        -->
        <typeAlias type="com.lng.pojo.User" alias="user"/>
    </typeAliases>

也能够指定一个包名,Mybatis会在包名下面搜索须要的JavaBean,如:

<!--使用typeAliases用于配置别名。-->
    <typeAliases>
        <!--用于指定要配置别名的包,当指定以后,该包下的实体类都会注册别名,而且类名就是别名,不在区分大小写-->
        <package name="com.lng.pojo"/>
    </typeAliases>

如有注解,则别名为其注解值,如:

@Alias("user")
public class User {
  ...
}

注意:基本数据类型及其包装类和一些经常使用的类,Mybatis在加载的时候已经把经常使用的数据类型注册了别名

其余配置

设置

  • 设置(settings)相关
    • 懒加载
    • 日志实现
    • 缓存开启
  • 一个完整的settings元素的实例以下:
<settings>
 <setting name="cacheEnabled" value="true"/>
 <setting name="lazyLoadingEnabled" value="true"/>
 <setting name="multipleResultSetsEnabled" value="true"/>
 <setting name="useColumnLabel" value="true"/>
 <setting name="useGeneratedKeys" value="false"/>
 <setting name="autoMappingBehavior" value="PARTIAL"/>
 <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
 <setting name="defaultExecutorType" value="SIMPLE"/>
 <setting name="defaultStatementTimeout" value="25"/>
 <setting name="defaultFetchSize" value="100"/>
 <setting name="safeRowBoundsEnabled" value="false"/>
 <setting name="mapUnderscoreToCamelCase" value="false"/>
 <setting name="localCacheScope" value="SESSION"/>
 <setting name="jdbcTypeForNull" value="OTHER"/>
 <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

类型处理器

  • 不管是Mybatis在预处理语句(PreparedStatement)中设置一个参数时,仍是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式实现Java类型和JDBC类型的互相转化
  • 能够本身重写类型处理器或建立本身的类型处理器来处理不支持的或非标准的类型【了解便可】

对象工厂

  • Mybatis每次建立结果对象的新实例时,他都会使用一个对象工厂(ObjectFactory)实例来完成
  • 默认的对象工厂须要作的仅仅是实例化目标类,要么经过默认构造方法,要么在参数映射存在的时候经过有参构造方法来实例化
  • 若是想覆盖对象工厂的默认行为,则能够经过建立本身的对象工程来实现【了解便可】
相关文章
相关标签/搜索