javaweb实训第六天下午——Mybatis基础(2)https://developer.aliyun.com/article/1415613
6.4.2.方式二:
1.通过mysql函数获取到刚插入记录的自增主键:LAST_INSERT_ID(),但是是在insert之后调用此函数。
XxxMapper写法: public interface ProductMapper { //自增长ID void insert2(Product product); } XxxMapper.xml写法: <!-- void insert2(Product product) --> <insert id="insert2"> <!-- 将插入数据的主键返回,返回到product对象中 SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用于自增主键 keyProperty:将查询到主键值设置到parameterType指定的对象的那个 resultType:指定SELECT LAST_INSERT_ID()的结果类型selectKey中resultType属性指定期望主键的返回的数据类型, keyProperty属性指定实体类对象接收该主键的字段名 order属性指定执行查询主键值SQL语句是在插入语句执行之前还是之后(可取值:after和before) 注:mysql用after,oracle用before --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long"> SELECT LAST_INSERT_ID() </selectKey> insert into product(productName) values(#{productName}) </insert> 测试: @Test public void testInsert(){ SqlSession session = MybatisUtil.getSqlSession(); ProductMapper mapper = session.getMapper(ProductMapper.class); Product product = new Product(); product.setProductName("绿茶111222"); System.out.println("====执行前===="+product.getId()); mapper.insert2(product); System.out.println("====执行后===="+product.getId()); session.commit(); session.close(); }
7.Mybtis使用细节
7.1.查看MyBatis运行日志
7.1.1.为什么需要日志
在使用MyBatis的很多时候,我们需要把日志打印出来,帮助我们进行分析与排错。特别是大家现在学习阶段,要求大家都MyBatis的日志打开;
7.1.2.常见的日志框架
System.out.print(“xxxx”)
写一个日志框架 dblLog.jar(yhptest)
Log log = LogFactory.getLog(this.class)
log.error/Info/warn…
写一个日志框架 dzlLog.jar(ttttt)
Log log = Factory.getLog(this.class)
log.error/Info/warn…
定义标准
(1)新写的日志框架按照日志标准来做;
(2)以前的日志框架使用适配器来做适配;
标准:slf4j(标准) – commons.logging,log4j(实现)
7.1.3.Log4j日记实现
Log4j主要用于日志信息的输出。可以将信息分级别(严重fatal、错误error、警告warn、调式debug、信息info)按不同方式(控制台、文件、数据库)和格式输出;
实现步骤如下:
(1)导入log4j的jar包(3个);
(2)在classpath下添加log4j.properties【名字不能改】;
(3)日志级别:debug(调试时用)、info、warn、error(运行时用)
(4)在日志中我们可以看到执行的SQL语句,可以看到我们传递的参数
Log4j主要有以下3部分组件构成:
(1)日志器(级别Logger):负责消息输出,提供了各种不同级别的输出方法;
(2)输出器(方式Appender):负责控制消息输出的方式,例如输出到控制台、文件输出等;
(3)布局器(格式器,Layout):负责控制消息的输出格式;
要在项目中打开日志,大家在资源文件根目录下创建一个log4j.properties【名称不要修改】的文件,并把下面的代码拷备到里面:
#日志器logger #輸出器appender #布局器layout #1.控制台输出 #指定日志器的输出级别和日志器的名称 #log4j.rootLogger=info,myconsole #指定输出器 #log4j.appender.myconsole=org.apache.log4j.ConsoleAppender #指定布局器 #log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout #2.文件输出.txt #指定日志器的输出级别和日志器的名称 #log4j.rootLogger=error,myfile #指定输出器 #log4j.appender.myfile=org.apache.log4j.FileAppender #log4j.appender.myfile.File=E:\\log4j.txt #指定布局器(普通布局表示文本输出) #log4j.appender.myfile.layout=org.apache.log4j.SimpleLayout #3.文件输出.html #指定日志器的输出级别和日志器的名称 #log4j.rootLogger=error,myhtml #指定输出器 #log4j.appender.myhtml=org.apache.log4j.FileAppender #log4j.appender.myhtml.File=D:\\log4j.html #指定布局器(网页布局) #log4j.appender.myhtml.layout=org.apache.log4j.HTMLLayout #4.控制台输出+文件输出.txt #指定日志器的输出级别和日志器的名称 #log4j.rootLogger=error,con,file #指定输出器 #log4j.appender.con=org.apache.log4j.ConsoleAppender #log4j.appender.file=org.apache.log4j.FileAppender #log4j.appender.file.File=D\:\\log4j.txt #指定布局器(网页布局) #log4j.appender.con.layout=org.apache.log4j.SimpleLayout #log4j.appender.file.layout=org.apache.log4j.SimpleLayout #5.控制台输出+自定义布局 log4j.rootLogger=DEBUG,my #指定输出器 log4j.appender.my=org.apache.log4j.ConsoleAppender #指定布局器(自定义布局) #指定布局为自定义布局 log4j.appender.my.layout=org.apache.log4j.PatternLayout #指定在自定义布局的格式,%d -- 表示当前系统时间,%t -- 执行该业务的线程名称,%p -- 日记器的级别,-5 -- 5表示输出字符的个数,符号表示右对齐 #%c -- 表示指定业务所在的类的完全限定名(包名.类名),%m -- 输出额外信息,%n -- 表示换行 log4j.appender.my.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n #设置package(可以是自定义的包也可以是api的包)输出级别 log4j.logger.org.springframework=info log4j.logger.cn.itsource=debug
注意:在上面的标红部分是我们需要修改的,它大概表示为当前会打印哪些位置下面文件的日志;如果配置成功,那么在MyBatis运行操作数据时就可以看到相应的日志了;
7.2.MyBatis中使用别名
- 别名就是为类取得小名,以后可以使用小名代替真实名称,在Mybatis中,将实体类的名称简化,方便开发,别名分为内置别名和自定义别名;
7.2.1.内置别名
7.2.2.自定义别名
<typeAliases> <!-- 单个配置:测试时使用 --> <typeAlias type="cn.itsource.domain.Dept" alias="Dept" /> <!-- 包的配置:项目中使用,添加了包之后,类名或类名首字母小写就是别名 --> <package name="cn.itsource.domain" /> </typeAliases>
7.3.#与$区别
7.3.1.#{OGNL表达式}
MyBatis会把这个表达式使用?(占位符)替换,作为一个sql参数使用:推荐使用。比如name的值为:
定义SQL: select * from t_user where name = #{name}
最终SQL: select * from t_user where name = ?
7.3.2.${OGNL表达式}
- MyBatis会把这个表达式的值替换到sql中,作为sql的组成部分。把获取到值直接拼接到SQL中;
- 如果sql中使用${OGNL},并且参数的类型是(integer、string…)那么OGNL表达式可以写成任意形式;
7.3.3.${OGNL}表达式的应用场景
- 不能用在登录,会出现sql注入
比如登录功能,在输入name的时候可以人为的制造成功:
User user=new User(); user.setName("\"admin\" or \"1=1\" "); user.setPassword("\"admin\" "); 定义SQL: select id,name,password from t_user where name = ${name} and password=${password} 最终SQL: select id,name,password from t_user where name="test" or "1=1" and password="test" 出现sql注入
用在order by + limit的场景
注意:除了要拼接sql结构体要用$(是直接拼接sql),其他都用#,因为用#会替换为?,最终通过PreparedStament来设置参数,不会有sql注入问题;
8.课程总结
8.1.重点
- Mybatis入门
- Mybatis的CRUD操作
- Mybatis使用细节
8.2.难点
- Mybatis使用细节
- 定位错误
8.3.如何掌握
- 勤加练习
- 学会看说明手册
8.4.排错技巧(技巧)
9.常见问题
没有导入数据库的驱动包;
在XML中很多都是字符串,细心,不要写错;
在映射文件中全限定名可能会写错;
找不到相应的Statement(sql语句)
(1)找SQL的Statement写错了;
(2)在核心XML中没有找相应的映射文件;
在我们调用Statement(sql语句的时候),经常会忘记传参;
执行成功后,数据库却没有反映,很有可能是没有提交事务;
可能我们忘了写执行的代码了;
错误一定要打印出来(执行的时候没效果,但是又不报错);
Mapper中就算一个语句没有使用,它的错也可能会影响到其它正确的语句;
框架的错往往从后向前找;
很多同学没有取别名,但是他一直去用;
字符编码:useUnicode=true&characterEncoding=UTF-8
10.课后练习
- 课堂代码1-2遍;
11.面试题
- Mybatis和Jdbc联系和区别; (预计10分钟完成)
- Mybatis和Jpa实现框架Hibernate区分和联系; (预计10分钟完成)
12.扩展知识或课外阅读推荐(可选)
12.1.扩展知识
Mybatis与Hibernate区别?
- Hibernate
(1)优点:对于简单的CRUD可以不写SQL语句,代码可移植(可以更换不同的数据库);
(2)缺点:
①Hibernate不够灵活,对于复杂的SQL支持较弱;
②HQL黑箱操作,调优复杂度高;
③不适合大型互联网项目的高性能要求;
Mybatis
(1)优点:高度灵活,自己操作SQL,方便优化。学习门槛低,易于维护和开发;
(2)缺点:由于每种数据库的SQL语句是不一样的,所以代码不可移植;
12.2.课外阅读