Day13 学习Mybatis框架的使用

学习Mybatis框架的使用

1. 快速上手

  1. Mybatis框架作用:是一款持久层框架,减轻在JavaWeb基础时进行JDBC数据库的CRUD操作,可以直接进行实体类与数据库的关系映射
  2. 使用Mybatis需要的jar包:数据库驱动包(这里使用Mysql),Mybatis包,Junit(测试程序需要的包) maven依赖
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.32</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>RELEASE</version>
    </dependency>
</dependencies>
  1. 根据官网:

https://mybatis.org/mybatis-3/zh/getting-started.html

  1. 写mybatis-config.xml配置文件,从 XML 中构建 SqlSessionFactory(可以产生执行Sql的对象)
<?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="${driver}"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mysql_test?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="UserMapper.xml"/>
  </mappers>
</configuration>
  1. 创建需要操作的数据表对应的实体类(poji),字段和属性名一一对应,类型也要一样,然后创建操作实体类对应的接口UserMapper,这里不需要实现类,需要与之对应的xml文件(相当于实现类)UserMapper.xml,需要在主配置文件中注册。
    这里的namespace与接口的全限类名一样,每个id对应接口中的方法名
public interface UserMapper {
    List<User> selectUser();
}
<?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.UserMapper">    
  <select id="selectUser" resultType="返回类型的全限的类名">
    select * from User
  </select>
</mapper>
  1. 从 SqlSessionFactory 中获取 SqlSession,执行sql,返回结果
SqlSession session = sqlSessionFactory.openSession()
UseMapper mapper = session.getMapper(UseMapper.class);  
List<User> users= mapper.selectUser();

2.实现增删改查操作(增删改操作需要提交事务)

  • 在快速入门的时候,已经写好了mybatis-config.xm,并将UserMapper.xml进行注册,也写好了pojo实体类,与之对应的接口UserMapper。
  • 现在实现一个插入数据库的操作,只需要修改 UserMapper.xml 和 接口UserMapper
  • 实现插入一个用户的操作,在 UserMapper.xml中,标签insert ,parameterType=“传入的参数类型,自定义对象需要全限类名”
<!-- id为接口的方法名 传入对象 键为属性值 使用#{属性值}取值 -->
<insert id="insertUser" parameterType="com.User">
		insert into user(`name`,gradeid,gender) VALUES (#{name},#{gradeid},#{gender})
</insert>
  • 修改操作同理,只需要在接口中添加一个方法,和在 UserMapper.xml 中配置sql就可以啦
<update id="updateById" parameterType="com.xxx.pojo.User">
   update user set `name`=#{name},gender=#{gender} where id=#{id};
</update>
  • 删除操作同理,只需要在接口中添加一个方法,和在 UserMapper.xml 中配置sql就可以啦
<delete id="deleteById" parameterType="int">
 		delete from user where id=#{id}
</delete>
public interface UserMapper {
    // 查询所有数据
    List<User> selectUser();
    // 插入一条数据
    int insertUser(User user);
    // 根据id修改值
    int updateById(User user);
    // 根据id删除一条数据
    int deleteById(int id);
}

3.参数可以传递Map,直接取键就行了 , 实现分页

<!-- 传入的类型为Map,按键取值就行 -->
<update id="updateMap" parameterType="map">
	update user set `name`=#{mapname},gender=#{mapgender} where id=#{mapid};
</update>

分页操作可以传递map:
第一种使用map:

SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("startIndex",5);
map.put("pageSize",5);
List<User> users = mapper.selectUserLimit(map);
for (User user : users) {
    System.out.println(user);
}
sqlSession.close();

<select id="selectUserLimit" parameterType="map" resultType="user">
  select * from user limit #{startIndex},#{pageSize}
</select>

第二种在Java层面进行分页,还是查询全部: 一定要使用原始的方法:sqlSession.selectList , 传入分页的对象

SqlSession sqlSession = MybatisUtil.getSqlSession();
RowBounds rowBounds = new RowBounds(0, 6);
List<User> users = sqlSession.selectList("com.xxx.Dao.UserMapper.selectUser", null, rowBounds);
for (User user : users) {
    System.out.println(user);
}
sqlSession.close();

<select id="selectUser" resultType="user">
 		select * from user
</select>
<!-- 模糊查询 -->
<select id="selectUserLike" resultType="com.xxx.pojo.User">
  	select * from user where name LIKE "%王%"
 </select>

4.Mybatis核心配置文件的解析

  1. 配置数据库连接的环境,默认使用JDBC(有事务),POOLED(连接池),可以配置多套数据环境,但每个 SqlSessionFactory 实例只能使用一种
  2. 可以使用 引用外部的配置文件,
    这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置
    但是如果重名外部配置文件的会使用(覆盖掉内部的)
<properties resource="db.properties">
    <property name="password" value="jkj"/>
</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>
  1. 起别名
    有两种方式 一种指定别名,一种扫描包,别名默认为为首字母小写的类名,可以使用注解起别的@Alias(“别名”)
<typeAliases>
		<typeAlias type="类的全限名" alias="别名"/>
		<typeAlias type="com.xxx.pojo.User" alias="User"/>
</typeAliases>
<typeAliases>
	<package name="实体类所在的包的路径"/>
   	<package name="com.xxx.pojo"/>
</typeAliases>
  1. Mapper 映射器
<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <!-- 如果使用配置文件需要将配置文件和接口放在同一文件中且同名 -->
  <mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <!-- 如果使用配置文件需要将配置文件和接口放在同一文件中且同名 -->
  <package name="org.mybatis.builder"/>
</mappers>
  1. settings中配置日志输出

https://blog.csdn.net/sinat_30185177/article/details/73550377

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>   可以直接打印在控制台
    <setting name="logImpl" value="LOG4J"/>  需要配置文件 log4j.properties
</settings>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

5. resultMap 解决实体类属性名和数据库字段名不一致问题

  1. 可以在查询时起别名
<select id="selectUser" resultType="user">
 		select id,name,gradeid,gender as sex from user
</select>
  1. 使用resultMap ,可以只写不一致的那个字段
<resultMap id="userType" type="User">
    <result column="gender" property="sex"/>
</resultMap>
<select id="selectUser" resultMap="userType">
    select * from user
</select>

6. 使用注解

  1. 增删改查的注解 @Insert,@Update,@Delete,@Select
@Insert("insert into user(name,gradeid,gender) values(#{name},#{gradeid},#{sex})")
int InsertUser(User user);
  1. 多个参数使用注解@Param(“参数名”)
User selectUserById(@Param("uid") int id);  // 会使用注解内的参数名
  1. 注解和配置文件可以一起使用,但对于同一个方法只能选择一个
    参考别人的博客:

https://blog.csdn.net/liangcheng0523/article/details/106882135/

7.多对一查询(实体类中有对象)

public class User {
    private int id;
    private String name;
    private String gender;
    private Grade grade;
}
public class Grade {
    private int id;
    private String grade;
}
<mapper namespace="com.xxx.Dao.UserMapper">
    <resultMap id="userGrade" type="user">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <!-- property是属性 column是字段 javaType表示属性对应的类型  select表示根据哪条sql查询,依靠字段column="gradeid",也是select="selectGrade"查询语句的参数 -->
        <association property="grade" column="gradeid" javaType="grade" select="selectGrade"/>
    </resultMap>
    <select id="selectUser" resultMap="userGrade">
        select * from user
    </select>
<!-- 子查询形式实现 -->
    <select id="selectGrade" resultType="grade">
        select * from grade where id=#{gradeid}
    </select>
</mapper>
<!--===========================================================================-->
<!-- 结果集嵌套映射实现 -->
<resultMap id="userGrade2" type="user">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="gender" column="gender"/>
    <!-- property表示实体类User中的对象属性 javaType表示属性的类型(没有起别名就写全限类名)  -->
    <association property="grade" javaType="grade">
    	<!-- property 表示Grade实体类的普通属性  column表示查询结果中 字段对应的值  -->
        <result property="grade" column="grade"/>
        <result property="id" column="gid"/>
    </association>
</resultMap>
<!-- 联表查询 -->
<select id="selectUser2" resultMap="userGrade2">
    select u.id,u.name,u.gender,g.grade,g.id gid from user u,grade g where u.gradeid=g.id
</select>

8.一对多(实体类有集合)

public class User {
    private int id;
    private String name;
    private String gender;
    private int grideid;
}
public class Grade {
    private int id;
    private String grade;
	// 一对多的列表集合
    private List<User> users;
}
<!-- 结果集嵌套映射 -->
<mapper namespace="xxx.Dao.GradeMapper">
    <resultMap id="gradeUser" type="grade">
        <result property="id" column="gid"/>
        <result property="grade" column="grade"/>
        <!-- 列表的类型使用 ofType 其实和javaType作用相同 -->
        <collection property="users" ofType="user">
            <result property="id" column="uid"/>
            <result property="name" column="name"/>
            <result property="gender" column="gender"/>
            <result property="grideid" column="gid"/>
        </collection>
    </resultMap>
    <select id="getGradeList" resultMap="gradeUser">
        select u.id uid,u.name,u.gender,g.id gid,g.grade from user u,grade g where u.gradeid=g.id;
    </select>
<!-- ============================================================================= -->
<!-- 子查询形式 -->
<resultMap id="grades" type="grade">
        <result property="id" column="id"/>
        <result property="grade" column="grade"/>
        <collection property="users" ofType="user" column="id" select="selectByGradeId"/>
    </resultMap>
    <select id="gradeUser2" resultMap="grades">
        select * from grade
    </select>
    <select id="selectByGradeId" resultType="user">
        select * from user where gradeid=#{id}
    </select>
</mapper>

9.动态SQL 其中test中直接写键(传入的参数)不用 #{}/${}进行取值(好像会自动对键(传入的参数)进行取值再判断)

  1. if test必填,作为条件判断,若条件满足则添加包含的语句
<resultMap id="providerMap" type="smbmsProvider">
	  	<result property="proName" column="proName"/>
	    <result property="proContact" column="proContact"/>
	    <result property="proPhone" column="proPhone"/>
	    <result property="proAddress" column="proAddress"/>
</resultMap>
<select id="selectIf" resultMap="providerMap">
		 select proName,proContact,proPhone,proAddress from smbms_provider
		    <where>
		        <if test="pname != null">
		            proContact like "%"#{pname}"%"
		        </if>
		    </where>
</select>
  1. choose,when,otherwise 相当于java的switch,case,default 只会选择一句进行插入
<select id="selectChoose" resultMap="providerMap" parameterType="map">
    select proName,proContact,proPhone,proAddress from smbms_provider
    <where>
        <choose>
            <when test="proName != null">
                and proName like "%"#{proName}"%"
            </when>
            <when test="proDesc != null">
                and proDesc like "%"#{proDesc}"%"
            </when>
            <otherwise>
                and 1==1
            </otherwise>
        </choose>
    </where>
</select>
  1. trim,where,set
<!-- 等价于where -->
<trim prefix="where" prefixOverrides="and|or">
</trim>
<!-- 等价于set -->
<trim prefix="set" suffixOverrides=",">
</trim>
  1. foreach
<select id="selectForeach" resultMap="providerMap" parameterType="list">
    select proName,proContact,proPhone,proAddress from smbms_provider
    <where>
    	<!-- collection的参数表示键,如果传的是列表使用list,数组使用array,map则写map中可遍历的对象对应的键 例{"ids":[1,2,4,5]},就写ids  其他参数 item 遍历的每个值 open 以什么开始 separator 分隔符 close 以什么结束 -->
        <foreach collection="list" item="item" close=")" separator="," open="id in (">
            #{item}
        </foreach>
    </where>
</select>

10.缓存

  1. Mybatis默认开启一级缓存,即在一个sqlSession的开启和关闭之间存入一级缓存中,也就是在这之间有效,查询同一个Sql则从缓存中读取,不进行连接数据库
  2. 一级缓存失效: 1.查询同一个sql不同的数据(例如根据id查询,id不同) 2. 清除缓存sqlSession.clearCache();3. 不同的sqlSession
  3. 二级缓存:在主配置文件的Settings中配置开启缓存cache,然后在每个Mapper.xml中设置cache的属性<cache … />
  4. 二级缓存在命名空间有效,在同一个mapper的有效,sqlSession关闭则会将一级缓存的数据保存到二级缓存中
  5. 例如mapper.selectUser() 会先从二级缓存查询,没有则查询一级缓存,在没有则连接数据库查询
  6. 还可以自定义缓存

Mybatis-config.xml 头文件和Mapper.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>

</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=" ">

</mapper>

log4j.properties文件

log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/a.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值