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语句插入两条一模一样的数据时