SSM---Mybatis

图片
Hibernate(ORM(对象关系映射)框架):
		全自动化,但是不能指定sql,类似于全自动洗衣机,洗、脱水、烘干一起帮你做,但是如果你的衣服是要自然晾干的,就会麻烦,因为		 他是全自动的
Mybatis:轻量级框架,半自动化,可定制sql,存放在GitHut,之前叫ibatis,去了谷歌后改名为Mybatis	

配置文件同一放在resource目录下
xml文件中返回值为int型的时候不用写 
xxxMapper接口传入多个参数时,加上 @Param("xxx") 

每一个xxxMapper接口,对应一个同包同名xxxMapper.xml,
   	(1) 在xxxMapper.xml绑定xxxMapper接口
    <mapper namespace="com.gwq.mapper.xxxMapper">	
    
	(2) 并且去mybatis.xml配置文件中注册
    第一种方式(最使用,推荐使用)    
    <mappers>
        <mapper resource="com/gwq/mapper/UserMapper.xml"/>
    </mappers>
     第二种方式(有前提同包同名)    
    <mappers>
        <mapper class="com.gwq.mapper.UserMapper"></mapper>
    </mappers>
    第二种方式(有前提同包同名)
    <mappers>
        <package name="com.gwq.mapper"/>
    </mappers>

在这里插入图片描述

Mybatis(XML)

步骤

(1)第一步:配置pom.xml 导包、写外部引入<build></build>
(2)建包 mapper、pojo、utils、导jdbc.properties、写MybatisUtils工具类(SSM整合后不用)、写JavaBean、写Mapper抽象类、Mapper.xml、测试
(3)增删改一定要提交事务
    sqlSession.commit();	 sqlSession.close();

每一个xxxMapper.xml都要绑定对应接口全类型,并且去核心配置文件注册绑定	 
    <mappers>
        <mapper resource="com/gwq/mapper/UserMapper.xml"/>
    </mappers>
    
    <!--批量映射:resources建相同包名、与接口同名的xxxMapper.xml-->
    <mappers>
        <package name="com.gwq.mapper"/>
    </mappers>
    
    parameterType不需要写:Mybatis会帮我们自动匹配
    
    sql语句不用写分号 ;	
    增删改没有返回值,如果方法返回值int、long、Boolean, Mybatis会自动返回值正数、true 
    增删改要提交事务sqlSession.close
    sqlSession一定要close
    
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);	
	//获取到的mapper是接口BlogMapper的代理对象,动态代理实现

	resultType="全类名就行"  起别名以后大项目会乱
	如果返回的是多条记录的集合,resultType写集合里元素的类型  List<User> ==>resultType="User全类名"
    如果返回的是单条记录的集合,resultType	resultType="集合别名"	list、map
        
	    
   	方法传入多个参数:用map集合或者  @Param:为参数指定key
   	int updateBlog(@Param("a") int a,@Param("b") String b);
	mapper.updateBlog(a,b);
	
	int updateBlog(Map<String, Object> map);
	mapper.updateBlog(map);

	#{}:参数预编译,参数位置用?代替。安全,不会sql注入;在不支持参数预编译的位置(如表名)要进行取值就使用${}
	${}:不是参数预编译,直接sql语句拼串,存在sql注入

核心配置文件

**mabits-config.xml **

各属性的摆放顺序必须遵循:
        "properties"、"settings"、"typeAliases"、typeHandlers、objectFactory、objectWrapperFactory、					 reflectorFactory、plugins、"environments"、databaseIdProvider、"mappers"
<?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">

<!--	各各属性的摆放顺序
	"properties"、"settings"、"typeAliases"、typeHandlers、objectFactory、objectWrapperFactory、					 reflectorFactory、plugins、"environments"、databaseIdProvider、"mappers"
-->

<!--核心配置文件-->
<configuration>
    
    <!--   1. 直接引用resources目录下的文件,JDBC 引入配置文件-->
    <properties resource="jdbc.properties"/>
	<!-- 方式二:引入外部文件后,可以额外添加属性,如果属性名与外部配置文件一致,"优先使用外部配置文件的属性"--><!--
    <properties resource="jdbc.properties">
        <property name="name" value="123"/>
        <property name="pwd" value="1111"/>
    </properties>																				-->

    <settings>
        <!--开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>	
        <!--开启懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--数据库属性:a_count 与 pojo属性:aCount 之间的驼峰命名转换-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>	
        <!--	日志,记得导包<setting name="logImpl" value="LOG4J"/>    --> 
    </settings>
    
    
    <typeAliases>
        <!--自动扫描这个dao/mapper包的接口,别名为首字母小写类名-->
        <package name="com.gwq.dao"></package>
    </typeAliases>

  
     <!--每一个xxxMapper.xml都需要在Mybatis核心配置文件中配置,注意用/-->
    <mappers>
        <mapper resource="com/gwq/mapper(dao)/UserMapper.xml"/>		
    </mappers>
    <!-- 第二种方式(有前提同包同名)    
    <mappers>
        <mapper class="com.gwq.mapper(dao).UserMapper"></mapper>
    </mappers>
    第二种方式(有前提同包同名)
    <mappers>
        <package name="com.gwq.mapper(dao)"/>
    </mappers>
	-->
    
    
  
    <!--  SSM整合时这里不用  环境配置-->
    <environments default="development">    <!--选择默认哪套环境-->
        <!--第一套环境-->
        <environment id="development">
            <transactionManager type="JDBC"/>   <!--事务管理器(默认JDBC)-->
            <dataSource type="POOLED">          <!--数据源(默认POOLED)-->
                <property name="driver" value="${pro.driver}"/>
                <property name="url" value="${pro.url}"/>
                <property name="username" value="${pro.username}"/>
                <property name="password" value="${pro.password}"/>
            </dataSource>
        </environment>
        
    </environments>


</configuration>
MyBatis 可以配置多套环境,但是每个SqlSessionFactory实例只能选择一种环境。
MyBatis 默认的事务管理器是 JDBC,连接池:POOLED
  • 属性(properties)
properties 标签必须放最上面,要先引入才能被使用
在resources目录下放置配置文件:JDBC.properties 用来连接数据库
properties 引入外部文件,实现动态替换
方式一:只引入外部文件
<properties resource="jdbc.properties"/>
方式二:引入外部文件后,可以额外添加属性,如果属性名与外部配置文件一致,"优先使用外部配置文件的属性"
    <properties resource="jdbc.properties">
        <property name="name" value="123"/>
        <property name="pwd" value="1111"/>
    </properties>
  • 类型别名(typeAliases)
大项目建议直接使用 xxxmapper.xml 写sql时返回值或者参数全类名
resultType 和 parameterType 每次都要写类完全限定名
使用 typeAliases	来减少类完全限定名的冗余

在这里插入图片描述

注意:Mapper接口实现xml里的 namespace里的不能起别名,必须全类名
    <!--namespace=绑定一个对应的Mapper接口-->
<mapper namespace="com.gwq.mapper.UserMapper">

在这里插入图片描述

	<!--类型别名-->第一种方式
    <typeAliases>
         <typeAlias type="com.gwq.Pojo.User" alias="User"></typeAlias>
    </typeAliases>
	<!--类型别名-->第二种方式:	
	<typeAliases>
        <package name="com.gwq"></package>
    </typeAliases>
	
	<!--自动扫描这个包的类,别名为首字母小写类名,如果非要改别名,需要在实体类上加注解-->
    @Alias("hh")
    public class User {}
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
小写开头别名==>_
大写开头别名==>小写
别名					映射的类型
_byte					byte
_long					long
_short					short
_int					int
_integer				int
_double					double
_float					float
_boolean				boolean
string					String
byte					Byte
long					Long
short					Short
int						Integer
integer					Integer
double					Double
float					Float
boolean					Boolean
date					Date
decimal					BigDecimal
bigdecimal				BigDecimal
object					Object
map						Map
hashmap					HashMap
list					List
arraylist				ArrayList
collection				Collection
iterator				Iterator
  • 设置(settings)

    	<settings>
            <setting name="cacheEnabled" value="true"/>
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="logImpl" value="LOG4J"/>
        </settings>
    

在这里插入图片描述

在这里插入图片描述

第二步:写工具类MybatisUtils (SSM整合忽略这步)

package com.gwq.utils;		//不同项目下记得改这行
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 java.io.IOException;
import java.io.InputStream;
/**
 * 第一步,获取SqlSessionFactory对象
 * 第二步:获取SqlSession sql操作对象
 * sqlSessionFactory --> sqlSession
 * */
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            //这三句话固定的,用来获取SqlSessionFactory对象
            //直接读取resources下的配置文件
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取SqlSession sql操作对象
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

日志:排错

  • 日志工厂
在Mybatis核心配置文件mabits-config.xml中设置
掌握:LOG4J(要导包)、STDOUT_LOGGING(不用导包)
了解:SLF4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、NO_LOGGING

<!--settings只需要知道三种:-->
	<settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
  • Log4j (导包)
	可以控制每一条日志的输出格式
	可以通过配置文件来配置
		<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
  • Log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
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/guan.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
  • Log4j的简单使用
在要使用的Log4j的类中,导包import org.apache.log4j.Logger;
static Logger logger = Logger.getLogger(UserMapperTest.class);	//放在最外面提升作用域

运行完查看log目录下的信息

在这里插入图片描述

映射器(mappers)

  • 第一种方式
<!--每一个Mapper.xml(Mapper类的实现配置)都需要在Mybatis核心配置文件中注册
        这里的全类名别用.用/-->
    <mappers>
        <mapper resource="com/gwq/mapper/UserMapper.xml"/>
    </mappers>
  • 第二种方式(有前提)
	<mappers>
        <mapper class="com.gwq.mapper.UserMapper"></mapper>
    </mappers>
"注意点:"
	接口和它的Mapper配置文件必须同名
	接口和它的Mapper配置文件必须在同一个包下
  • 第三种方式(有前提,好用)
	<mappers>
        <package name="com.gwq.mapper"/>
    </mappers>
"注意点:"
	接口和它的Mapper配置文件必须同名
	接口和它的Mapper配置文件必须在同一个包下

在这里插入图片描述

xxxMapper.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.xml,一定要去mybatis核心配置文件中注册mapper-->
<!--namespace=绑定一个对应的Mapper接口-->
<mapper namespace="com.gwq.mapper.xxxMapper">
	<!--在这里面写sql-->
</mapper>

分页操作

//分页查询
    List<User> selectFy(Map<String,Integer> map);
<!--    分页查询用户-->
    <select id="selectFy" parameterType="map" resultType="user">
        select * from user limit #{startIndex},#{pageSize};
    </select>
//分页
    @Test
    public void FyselectTest(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex",5);
        map.put("pageSize",5);

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.selectFy(map);
        for (User user : users) {
            System.out.println(user);
        }
    }

MyBatis最强大元素:resultMap

结果集映射

解决属性名(Bean对象)和字段名(数据库)不一致的问题

	<resultMap id="MyresultMap" type="">
	         <result column="" property="" javaType="" />
	         <association property="" javaType="" column="" />
	         <collection property="" column="" javaType="" ofType="" >
	             <result column="" property=""/>
	         </collection>
	 </resultMap>

在这里插入图片描述

在这里插入图片描述

1.关联- association 【多对一】
2.集合- collection  【一对多】
3.javaType 	& 	ofType
   List<Student> eee;
   
   javaType 用来指定实体类属性的类型		==> javaType = "list"
   ofType 用来指定集合中的元素类型	   ==>  	ofType = "Student"
   property="eee"  对应属性的变量名
   column="" 		对应数据库里的字段名
  • 多对一处理 association
CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师'); 

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
    INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, '小明', 1); 
	INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, '小红', 1); 
	INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, '小张', 1); 
	INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, '小李', 1); 
	INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, '小王', 1);
	resultMap 元素是MyBatis中最强大的元素
	解决属性名(Bean对象)和字段名(数据库)不一致的问题
"需求":	(1)在JavaBean里面有两个类对象
                Student类对象:id、name、Teacher类对象
                Teacher类对象:id、name
      	  (2)在数据库里对应如下表
    	  现在需要查询Student表,展示所有学生的信息(包括老师name)

(1)方式一:按照结果嵌套处理(推荐)

<mapper namespace="com.gwq.mapper.StudentMapper"> 
		<!--按照结果嵌套处理-->
                <select id="getStudents2" resultMap="StudentTeacher2">
                    select s.id as sid,s.name as sname,t.name as tname
                    from student as s,teacher as t
                    where s.tid = t.id;
                </select>	<!--type:指定为哪个JavaBean自定义封装规则,全类名-->
                <resultMap id="StudentTeacher2" type="Student">		 
                    <result property="id" column="sid"/>
                    <result property="name" column="sname"/>
                    
                    <!--接下来的属性是一个Teacher对象 teacher,自定义这个对象的封装规则-->
                    <!--
                            collection:定义集合元素的封装
                            property=""	 指定哪个属性是集合属性
                            javaType:	指定对象类型,在association里面使用
                            ofType:		指定集合里元素的类型,在collection里面使用
                    -->
                    <association property="teacher" javaType="Teacher">
                        <result property="name" column="tname"/>
                    </association>
                </resultMap>
</mapper>
  • 方式二:级联属性(不推荐)

在这里插入图片描述

  • 方式三:按照查询嵌套处理(不推荐)
<mapper namespace="com.gwq.mapper.StudentMapper">
        <!--方式二:子查询	-->
        <select id="getStudents" resultMap="StudentTeacher">
            select * from student;
        </select>
        <!--    自定义一个resultMap-->
        <resultMap id="StudentTeacher" type="Student">
            <!--        字段名属性名相同的不用写,复杂的属性,需要单独处理
                        association 对象,    collection 集合           
						javaType=""  指定的属性的类型
						ofType=""	 集合中泛型的类型-->
            <result property="id" column="id"/>			//这两行可以不写
            <result property="name" column="name"/>		//这两行可以不写
            <association property="teacher" column="tid" javaType="Teacher" select="getTeacherById"/>
        </resultMap>
        <!--resultMap里面的嵌套查询teacher-->
        <select id="getTeacherById" resultType="Teacher">
            select * from teacher where id=#{tid};   
        </select>
</mapper>

一对多处理 collection

//学生类
public class Student {
    private int id;
    private String name;
    private int tid;
}
//教师类
public class Teacher {
    private int id;
    private String name;
    private List<Student> students;
}

方式一:按照结果嵌套处理(推荐)

	<select id="getTeacherById" resultMap="TeacherStudent">
            select s.id sid,s.name sname,t.name tname,t.id tid
            from student s,teacher t
            where s.tid = t.id and t.id = #{tid}
    </select>
    <resultMap id="TeacherStudent" type="Teacher">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
        
        	<!--
				collection:定义集合元素的封装
				property=""	 指定哪个属性是集合属性
				javaType:	指定对象类型,在association里面使用
				ofType:		指定集合里元素的类型,在collection里面使用
			-->
            <collection property="students" ofType="Student">
                <result property="id" column="sid"/>
                <result property="name" column="sname"/>
                <result property="tid" column="tid"/>
            </collection>
    </resultMap>

动态SQL

	动态sql就是根据不同条件生成不同的SQL语句
	if、choose、trim、foreach
建表blog
create table `blog`(
	`id` varchar(50) not null comment '博客id',
	`title` varchar(100) not null comment '博客标题',
	`author` varchar(30) not null comment '博客作者',
	`create_time` datetime not null comment '创作时间',
	`views` int(30) not null comment '浏览量'
)engine=innodb default charset=utf8;

insert into `blog`(`id`,`title`,`author`,`create_time`,`views`) values("121354","玩转同侪","过去",'2020-1-1',10000);

IF

在有where标签下,IF标签里的sql前面可以都加上and
	<select id="getBlogIF" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <if test="title != null">
                and title=#{title}
            </if>
            <if test="author != null">
                and author=#{author}
            </if>
        </where>
    </select>

where 最好加上

	我们的查询条件放在where标签中,每个and写在前面,where可以帮我们自动清除多余的and
<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG
          <where>
                <if test="state != null">
                    AND state = #{state}
                </if>
                <if test="title != null">
                    AND title like #{title}
                </if>
                <if test="author != null and author.name != null">
                    AND author_name like #{author.name}
                </if>
          </where>
</select>

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

choose、when、otherwise

从choose里面选择一个,只能选一个,相当于switch语句,没有符合条件时,选otherwise
<select id="findActiveBlogLike"  resultType="Blog">
  select * FROM BLOG WHERE state = ‘ACTIVE’
    <where>
        <choose>
                <when test="title != null">
                  AND title like #{title}
                </when>
                <when test="author != null and author.name != null">
                  AND author_name like #{author.name}
                </when>
                <otherwise>
                  AND featured = 1
                </otherwise>
      	</choose>
    	</where>
	</select>

set 修改语句

set 元素会动态地在行首插入 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>

sql片段(抽取sql)

<sql id="if-title-author">
    <if test="title != null">
         title=#{title},
    </if>
    <if test="author != null">
         author=#{author}
    </if>
</sql>
<select id="getBlogIF" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <include refid="if-title-author"> </include>
        </where>
    </select>

ForEach

在这里插入图片描述

查询第121555、121354号记录的博客
select * from blog where id in(xxx,xxx,xxx)
	<select id="queryBolgForEach" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <foreach item="id" collection="ids" 
                     open="id in (" 
                     separator=","
                     close=")">
                #{id}
            </foreach>
        </where>
    </select>
	@Test
    public void queryBolgForEachDemo(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        ArrayList<String> ids = new ArrayList<>();
        ids.add("121555");
        map.put("ids",ids);

        List<Blog> blogs = mapper.queryBolgForEach(@Param("ids")map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

缓存(Map实现)

	Mybatis两种缓存:LRU(默认,最近最少使用)、FIFO

一级缓存(SqlSession)

	与数据库同一次会话期间查询到的数据放在本地缓存中。
	在同一sqlSession.cloce之前,再次查询相同信息时,直接从缓存中拿,没必要再去查询数据库。
一级缓存失效的几种情况:
	1.一级缓存以一个sqlSession为单位。不同sqlSession查询同一数据
    2.sqlSession关闭后,此sqlSession一级缓存失效
    3.sqlSession期间执行增删改操作,会清空一级缓存
    4.手动清空:	sqlSession.clearCache();  只清一级缓存
	

二级缓存(全局)

作用域:namespace缓存、同一个xxxMapper.xml
开启条件:当有一个sqlSession close或者comit之后,二级缓存生效
		<setting name="cacheEnabled" value="true"/>			
		在mapper里面设置<cache/>
		JavaBean对象implements Serializable 序列化
当新的会话建立时,查询之前任意sqlSession查询的语句时,直接从缓存中拿。

在这里插入图片描述

<setting name="cacheEnabled" value="true"/>
也可以自定义参数
<cache
  eviction="FIFO"
  flushInterval="60000"			每隔60s刷新缓存
  size="512"
  readOnly="true"/>

<cache/>  和上面一样,只是上面的能看到参数(推荐)

缓存原理

在这里插入图片描述

缓存顺序:先看二级缓存 ==> 再看一级缓存 ==> 查询数据库

生命周期和作用域

在这里插入图片描述

  • SqlSessionFactoryBuilder
	一旦创建了 SqlSessionFactory 就不再需要它了 ==> 所以作为 "局部变量"  
  • SqlSessionFactory
	可以想象成:数据库连接池
    SqlSessionFactory在运行期间要一直存在 ==>  应用作用域  
    可以使用单例模式或者静态单例模式
  • SqlSession(用完关闭)
	相当于连接到连接池的一个请求
    SqlSession的实例不是线程安全的,因此不能被共享	==> 请求、方法作作用域
  • Mapper
	一个Mapper代表一个具体业务

其他技巧

Map<String,Object>万能

public static void updateBymapTest(){
        Map<String ,Object> map = new HashMap<String,Object>();
        map.put("id",30);
        map.put("name","老七");
        map.put("pwd","666666");

        try(final SqlSession sqlSession = MybatisUtils.getSqlSession()){
            final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.updateBymap(map);
            sqlSession.commit();
        }
    }
	<update id="updateBymap" parameterType="map">
        update book.user set `name`=#{name},`pwd`=#{pwd} where id=#{id};
    </update>
public static void addUserBymapTest(){
        Map<String ,Object> map = new HashMap<String,Object>();
        map.put("id",20);
        map.put("name","老六");
        map.put("pwd","666666");

        try(final SqlSession sqlSession = MybatisUtils.getSqlSession()){
            final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.addUserBymap(map);
            sqlSession.commit();
        }
    }
	<insert id="addUserBymap" parameterType="map">
        insert into book.user (`name`,`pwd`) values(#{name},#{pwd});
    </insert>
public static void getUserBymapTest(){
        Map<String ,Object> map = new HashMap<String,Object>();
        map.put("id",20);
        map.put("name","老六");
        map.put("pwd","666666");

        try(final SqlSession sqlSession = MybatisUtils.getSqlSession()){
            final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.getUserBymap(map);
            sqlSession.commit();

            System.out.println(user);
        }
    }
	<select id="getUserBymap" parameterType="map" resultType="com.gwq.Pojo.User">
        select * from book.user where id=#{id};
    </select>

模糊查询

 	//模糊查询
    public void selectUserByNameLikeTest(){
        //1.在java代码执行的时候,传递通配符 % %
        String like = "老%"; //查询一个name为老字开头的User集合
        try(SqlSession sqlSession = MybatisUtils.getSqlSession()){
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = mapper.selectUserByNameLike(like);
            for (User user : users) {
                System.out.println(user);
            }
        }
	<select id="selectUserByNameLike" resultType="com.gwq.Pojo.User">
        select * from user where `name` like #{name};
    </select>

在sql中使用通配符,更安全

	select * from user where name like "%"#{value}"%"

规定

1、在IEDA上连接数据库之后,book.user 表示book这个数据库上的user表,必须加book。没有连上的IDEA自带数据库直接表名就行	
	xml文件中返回值为int型的时候不用写 
        
 2.	Map传递参数,直接在sql中取key就行 #{key}
	对象传递参数,直接在sql中取属性就行 #{属性名}
	只有一个基本类型参数的情况下,可以直接在sql中取到
    多个参数用Map或者注解
 
 3.事务管理器:JDBC、MANAGED
    测试类方法必须为public
    insert没有return

    增删改需要提交事务
    sqlSession.commit();

    <delete id="delUserById" parameterType="int" >
            delete
            from book.user
            where `id`=#{id};
    </delete>
public static void getUserListTest(){
        //获取SqlSession对象,为什么放进try-with-resource,保证SqlSession对象能被关闭
        try (SqlSession sqlSession = MybatisUtils.getSqlSession()) {
            //逻辑代码
            }
        }
    }
public static void addUserByUserTest(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            int i = mapper.addUserByUser(new User("asd","1222223"));
            if(i>0) {
                System.out.println("插入成功");
            }
            sqlSession.commit();
            sqlSession.close();
    }
	<insert id="addUserByUser" parameterType="com.gwq.Pojo.User"  >
        insert into book.user(`name`,`pwd`) values(#{name},#{pwd});
    </insert>
public static void updateUserByIdTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.updateUser(new User("Double","8888"));
        if(i>0) {
            System.out.println("修改成功");
        }
        sqlSession.commit();
        sqlSession.close();
    }
	<update id="updateUser" parameterType="com.gwq.Pojo.User">
        update book.user set `name`=#{name},`pwd`=#{pwd};
    </update>
public static void delUserTest(){
        final SqlSession sqlSession = MybatisUtils.getSqlSession();
        final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.delUserById(1);
        if(i>0) System.out.println("删除成功");
        sqlSession.commit();
        sqlSession.close();

    }
	<delete id="delUserById" parameterType="int" >
        delete from book.user where `id`=#{id};
    </delete>

异常

一次insert语句插入两条一模一样的数据时

r" > insert into book.user(name,pwd) values(#{name},#{pwd});





```java
public static void updateUserByIdTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.updateUser(new User("Double","8888"));
        if(i>0) {
            System.out.println("修改成功");
        }
        sqlSession.commit();
        sqlSession.close();
    }
	<update id="updateUser" parameterType="com.gwq.Pojo.User">
        update book.user set `name`=#{name},`pwd`=#{pwd};
    </update>
public static void delUserTest(){
        final SqlSession sqlSession = MybatisUtils.getSqlSession();
        final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.delUserById(1);
        if(i>0) System.out.println("删除成功");
        sqlSession.commit();
        sqlSession.close();

    }
	<delete id="delUserById" parameterType="int" >
        delete from book.user where `id`=#{id};
    </delete>

异常

一次insert语句插入两条一模一样的数据时

在这里插入图片描述

全部评论

相关推荐

02-14 07:38
已编辑
门头沟学院 Java
2.4&nbsp;一面2.6&nbsp;二面2.9&nbsp;三面(hr面)2.13&nbsp;oc1.15号收到面试电话那会就开始准备,因为一开始没底所以选择推迟一段时间面试,之后开始准备八股,准备实习可能会问的东西,这期间hot100过了有六七遍,真的是做吐了快,八股也是背了忘,忘了背,面经也看了很多,虽然最后用上的只有几道题,可是谁知道会问什么呢自从大二上开始学java以来,一路走来真的太痛了,一开始做外卖,点评,学微服务,大二下五六月时,开始投简历,哎,投了一千份了无音讯,开始怀疑自己(虽然能力确实很一般),后来去到一家小小厂,但是并不能学到什么东西,而且很多东西都很不规范,没待多久便离开,大二暑假基本上摆烂很怀疑自己,大三上因为某些原因开始继续学,期间也受到一俩个中小厂的offer,不过学校不知道为啥又不允许中小厂实习只允许大厂加上待遇不太好所以也没去,感觉自己后端能力很一般,于是便打算转战测开,学习了一些比较简单的测试理论(没有很深入的学),然后十二月又开始继续投,java和测开都投,不过好像并没有几个面试,有点打击不过并没有放弃心里还是想争一口气,一月初因为学校事比较多加上考试便有几天没有继续投,10号放假后便继续,想着放假应该很多人辞职可能机会大一点,直到接到字节的面试,心里挺激动的,总算有大厂面试了,虽然很开心,但同时压力也很大,心里真的很想很想很想进,一面前几天晚上都睡不好觉,基本上都是二三点睡六七点醒了,好在幸运终于眷顾我一次了(可能是之前太痛了),一面三十几分钟结束,问的都不太难,而且面试官人挺好但是有些问题问的很刁钻问到了测试的一些思想并不是理论,我不太了解这方面,但是也会给我讲一讲他的理解,但是面完很伤心觉得自己要挂了。但是幸运的是一面过了(感谢面试官),两天后二面,问的同样不算难,手撕也比较简单,但也有一两个没答出来,面试官人很好并没有追问,因为是周五进行的二面,没有立即出结果,等到周一才通知到过了,很煎熬的两天,根本睡不好,好在下周一终于通知二面过了(感谢面试官),然后约第二天三面,听别的字节同学说hr面基本上是谈薪资了,但是我的并不是,hr还问了业务相关的问题,不过问的比较浅,hr还问我好像比较紧张,而且hr明确说了还要比较一下,我说我有几家的面试都拒了就在等字节的面试(当然紧张,紧张到爆了要),三面完后就开始等结果,这几天干啥都没什么劲,等的好煎熬,终于13号下午接到了电话通知oc了,正式邮件也同时发了,接到以后真的不敢信,很激动但更重要的是可以松一口气了,可以安心的休息一下了终于可以带着个好消息过年了,找实习也可以稍微告一段落了,虽然本人很菜,但是感谢字节收留,成为忠诚的节孝子了因为问的比较简单,面经就挑几个记得的写一下一面:1.实习项目的难点说一下2.针对抖音评论设计一下测试用例3.手撕:合并两个有序数组二面:1.为什么转测开2.线程进程区别,什么场景适合用哪个3.发送一个朋友圈,从发出到别人看到,从数据流转的角度说一下会经历哪些过程4.针对抖音刷到广告视频设计测试用例5.手撕:无重复字符的最长字串
查看8道真题和解析
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务