zoukankan      html  css  js  c++  java
  • mybatis学习笔记

    Mybatis

    官网:https://mybatis.org/mybatis-3/index.html

    下载地址:https://github.com/mybatis/mybatis-3/releases

    依赖:

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.2</version>
    </dependency>
    

    一、第一个Mybatis程序

    1.搭建环境

    搭建数据库

    CREATE DATABASE `mybatis`;
    USE `mybatis`
    CREATE TABLE `user`(
    	`id` INT(20) NOT NULL,
    	`name` VARCHAR(30) DEFAULT NULL,
    	`pwd` VARCHAR(30) DEFAULT NULL
    )ENGINE=INNODB DEFAULT CHARSET=utf8;
    INSERT INTO `user`(`id`,`name`,`pwd`)VALUES
    (1,"张三","123456"),
    (2,"李四","123456"),
    (3,"王五","123456")
    

    新建项目

    1. 普通maven项目
    2. 删除src目录
    3. 导入依赖 数据库,mybatis junit
    <!--        数据库连接-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
    <!--        mybatis-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.2</version>
            </dependency>
    <!--        junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13</version>
            </dependency>
    

    2.创建一个模块

    • 编写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>
        <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:3306/mybatis?useUnicode=true&amp;amp;characterEncoding=utf8&amp;amp;useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
    </configuration>
    
    • 编写mybatis工具类
    public class MybatisUtils {
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                String resource = "org/mybatis/example/mybatis-config.xml";
                InputStream inputStream = inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    }
    

    3.编写代码

    • 实体类
    • Dao接口

    二、CRUD

    流程:

    • 编写接口
    public interface UserDao {
    //    查询用户信息
        List<User> getUser();
    //    按id查询用户信息
        User getUser1(int id);
    //    增加用户信息
        int addUser(User user);
    //    修改用户信息
        int updateUser(User user);
    //    删除用户信息
        int delUser(int id);
    }
    
    • 编写对应的mapper中的sql语句
    <select id="getUser" resultType="com.study.pojo.User">
        select * from user
    </select>
    
    <select id="getUser1" resultType="com.study.pojo.User" parameterType="int">
        select * from user where id=#{id}
    </select>
    
    <insert id="addUser" parameterType="com.study.pojo.User">
        insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
    </insert>
    
    <update id="updateUser" parameterType="com.study.pojo.User">
        update user set name=#{name},pwd=#{pwd} where id=#{id}
    </update>
    
    <delete id="delUser" parameterType="int">
        delete from user where id=#{id}
    </delete>
    
    • 测试

    注意点:增删改 需要提交事务

    万能的Map

    使用Map传递参数:方便,灵活

    int addUser1(Map<String,Object> map);
    
    <insert id="addUser1" parameterType="map">
    insert into user (id,name ,pwd) values (#{id},#{name},#{pwd})
    </insert>
    
    public void addUser1(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserDao mapper = sqlSession.getMapper(UserDao.class);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("id",6);
    map.put("name","666");
    map.put("pwd","666666");
    mapper.addUser1(map);  
    sqlSession.commit(); 
    sqlSession.close();}
    

    模糊查询

    1.在传参时候写

    2.在sql拼接中使用通配符

    三、配置解析

    1.核心配置文件

    2.环境配置(environments)

    • <transactionManager type="JDBC"/>  默认为jdbc
      
    • <dataSource type="POOLED"> 数据源默认是池
      

    3.属性(properties)

    • 编写db.properties
    driver = com.mysql.jdbc.Driverurl = jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=falseusername = rootpassword = 123456
    
    • 在mybatis-config.xml中引入配置文件
    <!--核心配置文件-->
    <configuration>
    	<!--    引入外部属性-->
    	<properties resource="db.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="com/study/dao/UserDaoMapper.xml"></mapper>   
    </mappers>
    </configuration>
    

    4.类型别名(typeAliases)

    • 给实体类起别名
    <typeAliases>    <typeAlias type="com.study.pojo.User" alias="user"/></typeAliases>
    
    • 扫描包
    <typeAliases>    <package name="com.study.pojo"/></typeAliases>
    

    在实体类比较少时,使用第一种方式。

    实体类十分多,使用第二种。

    第一种可以DIY别名,第二种不行,非要改在实体上增加注解

    @Alias("hello")public class User {   ············    }
    

    5.设置(settings)

    • mapUnderscoreToCamelCase true
    • 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。

    6.映射器(mappers)

    • 注册绑定我们的Mapper文件

    方式一、resource

    <mappers>    <mapper resource="com/study/dao/UserDaoMapper.xml"></mapper></mappers>
    

    方式二、class

    <mapper class="com.study.dao.UserDaoMapper"/>
    
    • 注意点:
    • 接口和他的Mapper文件必须同名
    • 接口和他的Mapper文件必须在同一个包下

    方式三、package

    <package name="com.study.dao"/>
    
    • 注意点:
    • 接口和他的Mapper文件必须同名
    • 接口和他的Mapper文件必须在同一个包下

    7.生命周期和作用域

    四、解决属性名和字段名不一致问题

    1.暴力解决

    • 起别名
    <select id="getUser1" resultType="user" parameterType="int">
    	select id,name,pwd as password from user where id=#{id}
    </select>
    

    2.使用resultmap解决

    <resultMap id="userMap" type="user">
    	<result column="pwd" property="password"/>
    </resultMap>
    <!--查询语句-->
    <select id="getUser1" resultMap="userMap" parameterType="int"> 
    	select * from user where id=#{id}
    </select>
    

    五、日志

    1.日志工厂 logImpl

    数据库操作出现异常,需要排错。日志就是最好的助手。

    • SLF4J
    • LOG4J 【掌握】
    • LOG4J2
    • JDK_LOGGING
    • COMMONS_LOGGING
    • STDOUT_LOGGING 【掌握】
    • NO_LOGGING

    在mybatis文件中配置我们的日志

    <!--    日志输出--> 
    <settings>      
    	<setting name="logImpl" value="STDOUT_LOGGING"/>  
    </settings>
    

    1.STDOUT_LOGGING 【掌握】标准日志输出

    2.LOG4J

    1. 导包
    <!--        LOG4J-->
    <dependency>  
    	<groupId>log4j</groupId>   
    	<artifactId>log4j</artifactId>  
    	<version>1.2.17</version>
    </dependency>
    
    1. 写配置文件

    log4j.properties

    #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码log4j.rootLogger=DEBUG,console,file#控制台输出的相关设置log4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target = System.outlog4j.appender.console.Threshold=DEBUGlog4j.appender.console.layout = org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%c]-%m%n#文件输出的相关设置log4j.appender.file = org.apache.log4j.RollingFileAppenderlog4j.appender.file.File=./log/kuang.loglog4j.appender.file.MaxFileSize=10mblog4j.appender.file.Threshold=DEBUGlog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n#日志输出级别log4j.logger.org.mybatis=DEBUGlog4j.logger.java.sql=DEBUGlog4j.logger.java.sql.Statement=DEBUGlog4j.logger.java.sql.ResultSet=DEBUGlog4j.logger.java.sql.PreparedStatement=DEBUG
    
    1. <!--    日志输出-->    <settings>        <setting name="logImpl" value="LOG4J"/>    </settings>
      
    • 简单使用
    1. 导入包
    import org.apache.log4j.Logger;
    
    1. 日志对象
    static Logger logger = Logger.getLogger(UserDaoTest.class);
    
    logger.info("发送错误");logger.debug("发送错误");logger.error("发送错误");
    

    六、分页

    语法:select * from user limit startIndex,pageSize

    1.使用limit

    1.编写接口

    //    分页查询List<User> getUserByLimit(Map<String,Integer> map);
    

    2.Mapper.xml

    <!--分页查询-->
    <select id="getUserByLimit" parameterType="map" resultMap="userMap">
    	select * from user limit #{startIndex},#{pageSize}
    </select>
    

    3.测试

    @Testpublic void getUserByLimitTest(){
    	SqlSession sqlSession = MybatisUtils.getSqlSession();
    	UserDaoMapper mapper = sqlSession.getMapper(UserDaoMapper.class);
    	HashMap<String, Integer> map = new HashMap<>();
    	map.put("startIndex",0);
    	map.put("pageSize",3);
    	List<User> userList = mapper.getUserByLimit(map);
    for (User user : userList) {
    	System.out.println(user); 
    }
    	sqlSession.close();
    }
    

    2.RowBounds

    • 不在使用sql 分页
    1. 编写接口
    //    分页查询    List<User> getUserByRowBounds();
    
    1. Mapper.xml
    <!--分页查询-->
    <select id="getUserByRowBounds" resultMap="userMap"> 
    	select * from user
    	</select>
    
    1. 测试
    public void getUserByRowBounds(){
    	RowBounds rowBounds = new RowBounds(0,3);
    	SqlSession sqlSession = MybatisUtils.getSqlSession();
    	List<User> userList = sqlSession.selectList("com.study.dao.UserDaoMapper.getUserByRowBounds", null, rowBounds);
    	for (User user : userList) {
    		System.out.println(user);  
    	}
    	sqlSession.close();
    }
    

    3.分页插件

    • PageHelper 了解

    七、使用注解开发

    1.面向接口编程

    • 解耦

    2.使用注解开发

    • 底层实现机制:反射
    • 底层:动态代理
    1. 注解直接在接口上实现
    //    查询用户信息    @Select("select * from user")    List<User> getUser();
    
    1. 需要再核心配置文件中绑定接口
    <mappers>    <mapper class="com.study.dao.UserDaoMapper"/></mappers>
    
    1. 测试
    public void getUser(){
    	SqlSession sqlSession = MybatisUtils.getSqlSession();
    	UserDaoMapper mapper =  sqlSession.getMapper(UserDaoMapper.class);
    	List<User> user = mapper.getUser();
    	for (User user1 : user) {  
    		System.out.println(user1);
    	}   
    	sqlSession.close();
    }
    

    3.CRUD

    1. 工具类创建时候实现自动提交事务
    sqlSessionFactory.openSession(true);
    
    1. 编写接口,增加注解
    //    查询用户信息    
    @Select("select * from user")
    List<User> getUser();
    //    按id查询用户信息   
    @Select("select * from user where id=#{uid}")  
    User getUser1(@Param("uid") int id);
    //    增加用户信息  
    @Insert("insert into user(id,name,pwd) value(#{id},#{name},#{pwd})")  
    int addUser(User user);
    @Insert("insert into user(id,name,pwd) value(#{uid},#{uname},#{upwd})")  
    int addUser1(Map<String,Object> map);
    //    修改用户信息   
    @Update("update user set name=#{name},pwd=#{pwd} where id=#{id}")  
    int updateUser(User user);
    //    删除用户信息   
    @Delete("delete from user where id=#{id}") 
    int delUser(int id);
    
    1. 测试

    【注意:我们必须将接口注册绑定到 核心配置文件中】

    4.@Param注解

    • 基本类型参数或者String类型,需要加
    • 引用类型不需要
    • 如只有一个基本类型的话,忽略,
    • 我们在SQl中引用的就是我们这里的@param

    八、Lombok

    使用步骤:

    1. 在IDEA中安装Lombok插件
    2. 项目中导入lombokjar包
    <dependency>
    	<groupId>org.projectlombok</groupId> 
    	<artifactId>lombok</artifactId>   
    	<version>1.18.10</version>
    </dependency>
    
    1. 在实体类上面注解
    @Getter and @Setter
    @FieldNameConstants
    @ToString
    @EqualsAndHashCode
    @AllArgsConstructor
    @RequiredArgsConstructor and @NoArgsConstructor@Log,
    @Log4j,
    @Log4j2,
    @Slf4j,
    @XSlf4j,
    @CommonsLog,
    @JBossLog,
    @Flogger,
    @CustomLog
    @Data
    @Builder
    @SuperBuilder
    @Singular
    @Delegate
    @Value
    @Accessors
    @Wither
    @With
    @SneakyThrows
    @val
    @var
    
    @Data 无参构造 get set equals tostring hashCode
    @AllArgsConstructor 有参构造
    @NoArgsConstructor  无参构造
    
    @AllArgsConstructor
    @NoArgsConstructor
    public class User { 
    	private int id; 
    	private String name; 
    	private String pwd;
    }
    

    九、多对一处理

    环境搭建

    1. 导入lombok依赖
    2. 编写实体类
    3. 编写Mapper接口
    4. 编写对应的Mapper.xml文件
    5. 在核心配置文件中注册
    6. 测试

    1.按照查询嵌套处理

    <resultMap id="studentTeacher" type="student"> 
    	<result property="id" column="id"/>  
    	<result property="name" column="name"/>
    <!--复杂的属性我们需要单独处理-->  
    	<association property="teacher" javaType="Teacher" column="tid" select="getTeacher" /></resultMap> 
    <select id="getStudent" resultMap="studentTeacher">   
    	select * from student   
    </select>
    <select id="getTeacher" resultType="Teacher">  
    	select * from teacher where id=#{tid}  
    </select>
    

    2.按照结果嵌套处理

    <resultMap id="studentTeacher1" type="student">  
    	<result property="id" column="sid"/>  
    	<result property="name" column="sname"/>  
    	<association property="teacher" javaType="Teacher">   
    		<result property="id" column="tid"/>   
    		<result property="name" column="tname"/> 
    	</association>
    </resultMap>
    <select id="getStudent1" resultMap="studentTeacher1">  
    	select s.id sid,s.name sname,t.id tid,t.name tname from student s,teacher t where s.tid=t.id
    </select>
    

    十、一对多处理

    1.按照结果处理

    <!--    根据结果集查询-->  
    <resultMap id="TeacherStudent" type="Teacher">    
    	<result property="id" column="tid"/>  
    	<result property="name" column="tname"/>   
    	<collection property="students" ofType="student">  
    		<result property="id" column="sid"/>     
    		<result property="name" column="sname"/>    
    	</collection>   
    </resultMap>  
    <select id="getTeacher" resultMap="TeacherStudent">   
    	select t.id tid,t.name tname,s.id sid,s.name sname from student s,teacher t where s.tid=t.id and t.id=#{tid}   
    </select>
    

    2.按照查询嵌套处理

    <!--    按照查询嵌套处理-->
    <resultMap id="TeacherStudent1" type="Teacher"> 
    	//column="id" 是传参作用  
    	<collection property="students" javaType="ArrayList" ofType="student" select="getStudent" column="id"/>
    </resultMap>  
    <select id="getTeacher1" resultMap="TeacherStudent1"> 
    	select * from teacher where id=#{tid}</select><select id="getStudent" resultType="student">   select * from student where tid=#{tid}
    </select>
    

    十一、动态SQL

    搭建环境

    CREATE TABLE `blog`(
    `id` VARCHAR(50) NOT NULL COMMENT &#39;博客id&#39;,
    `title` VARCHAR(100) NOT NULL COMMENT &#39;博客标题&#39;,
    `author` VARCHAR(30) NOT NULL COMMENT &#39;博客作者&#39;,
    `create_time` DATETIME NOT NULL COMMENT &#39;创建时间&#39;,`
    views` INT(30) NOT NULL COMMENT &#39;浏览量&#39;
    )ENGINE=INNODB DEFAULT CHARSET=utf8
    

    IF

    <select id="getBlogIF" parameterType="map" resultType="Blog"> 
    	select * from blog where 1=1   
    	<if test="title != null">     
    		and title = #{title}   
    	</if>   
    	<if test="author != null"> 
    		and author = #{author}  
    	</if>
    </select>
    

    Where

    • where标签会自动去除 and
    <select id="queryBlogChoose" resultType="Blog">
    	select * from blog   
    	<where>    
    		<if test="title != null">       
    			title = #{title}    
    		</if>      
    		<if test="author != null">   
    			and author = #{author}  
    		</if>  
    	</where>
    </select>
    

    choose、when、otherwise

    • 相对于是 switch
    • 按顺序 只要有成立的 就返回
    • 如果 都不成立就走 othorwise中的
    <select id="queryBlogChoose" resultType="Blog"> 
    	select * from blog   
    	<where>      
    		<choose>     
    			<when test="title != null">    
    				title = #{title}    
    			</when>       
    			<when test="author != null">    
    				and author = #{author}   
    			</when>       
    			<otherwise>   
    				views = #{views}   
    			</otherwise>   
    		</choose>  
    	</where>
    </select>
    

    set

    <update id="updateBlog" parameterType="map">  
    	update blog  
    	<set>   
    		<if test="title != null">  
    			title = #{title},    
    		</if>    
    		<if test="author != null">   
    			author = #{author}    
    		</if>  
    	</set>   
    	where id = #{id}
    </update>
    

    trim

    • 使用trim 实现set标签
    <update id="updateBlog" parameterType="map">
    	update blog  
    	<trim prefix="set" suffixOverrides=",">   
    		<if test="title != null">   
    			title = #{title},   
    		</if>      
    		<if test="author != null">     
    			author = #{author}   
    		</if>  
    	</trim> 
    	where id = #{id}
    </update>
    
    • 使用trim 实现where标签
    <select id="queryBlogChoose" resultType="Blog">  
    	select * from blog 
    	<trim prefix="where" prefixOverrides="and | or">  
    		<choose>     
    			<when test="title != null">  
    				title = #{title}     
    			</when>       
    			<when test="author != null">    
    				and author = #{author}  
    			</when>     
    			<otherwise>     
    				views = #{views}   
    			</otherwise>  
    		</choose> 
    	</trim>
    </select>
    

    SQL片段

    • 有的时候,我们可能需要将一些功能的部分抽取出来,方便复用

    使用方法:

    • 使用sql标签
    • 使用include标签
    <sql id="if-title-author"> 
    	<if test="title != null">   
    	title = #{title},  
    	</if>   
    	<if test="author != null">  
    	author = #{author}   
    	</if>
    </sql>
    <update id="updateBlog" parameterType="map">  
    	update blog 
    	<trim prefix="set" suffixOverrides=",">
    		<include refid="if-title-author"></include>  
    	</trim>  
    	where id = #{id}
    </update>
    

    注意事项:

    • 不要存在where标签

    Foreach

    需求实现:

    select * from blog where 1=1 and (id=1 or id=2 or id=3)
    
    <!--select * from blog where 1=1 and (id=1 or id=2 or id=3)-->
    <select id="queryBlogForeach" parameterType="map" resultType="blog">   
    	select * from blog  
    	<where>   
    	<foreach collection="ids" item="id" open="and (" close=")" separator="or">      
    		id=#{id} 
    	</foreach>
    	</where>
    </select>
    
    • 注意这里collection="ids" 传的参数是 集合的名字 不需要加#{}

    总结建议

    • 先在MySql中写出完整的语句,再去修改成为我们的动态sql即可

    十二、缓存

    一级缓存SqlSession

    • 默认是开启的,无法关闭
    • 只在一次SqlSession中有效,也就是在得到连接-关闭连接有效
    • update insert delete操作会清除缓存
    • SqlSession.cleanCache()手动清除缓存

    二级缓存nameSpace

    • 只要开启了二级缓存,在同一个Mapper下有效
    • 所有数据都会先放在一级缓存中
    • 只有当会话提交,或关闭的时候,才会提交到二级缓存

    使用方法:

    1. 显示开启二级缓存
    <!--        开启二级缓存-->        <setting name="cacheEnabled" value="true"/>
    
    1. 在 Mapper.xml中写入
    <cache/>
    

    ​ 也可以自定义一些参数

    <cache  eviction="FIFO"			  flushInterval="60000"  size="512"  readOnly="true"/>
    
    1. 测试

    问题:实体类需要序列化,继承 Serializable

    public class Blog implements Serializable 
    

    缓存原理

    1. 先查二级缓存
    2. 在查一级缓存
    3. 都没有再去数据库查找

    自定义缓存-ehcache

    1. 导如jar包
    <dependency>    <groupId>org.mybatis.caches</groupId>    <artifactId>mybatis-ehcache</artifactId>    <version>1.1.0</version></dependency>
    
  • 相关阅读:
    C#中两个日期类型的变量如何进行比较
    Ajax基本原理讲解 (引用别人文章)
    Ajax程序设计入门
    ASP.NET中如何调用存储过程
    删除SAM文件真的能够消除XP系统管理员的密码吗?
    用XMLHttpRequest和struts实现AJAX(译)
    关于邮件系统域名(DNS)设置的小常识
    输出各种二进制流的格式
    WPF 3D编程介绍
    WPF 3D学习笔记
  • 原文地址:https://www.cnblogs.com/20183544-wangzhengshuai/p/15237061.html
Copyright © 2011-2022 走看看