第1章 案例简介
第2章 实战第一部----黎明前的黑暗
开发流程1:
开发流程2:
开发流程3:
JSP页面放在web-inf下便于控制和管理。必须从后台才能访问到JSP,这样便于控制。放在外面是直接可以访问到的,除非拦截*.jsp
最好不要写成select *,select *数据库引擎还得用*去解析一遍,解析成列名,所以最好写“select 列名”
servlet一般就做这几件事
1.接收页面的值
2.向页面传值
3.业务需要,调用service。
4.向页面跳转。
dao层一般是跟表相关的,跟哪张表操作的就是哪个dao,例如有一张表Message,就叫MessageDao
第3章 实战第二部---- Mybatis 来袭
发布版,下载。
源码包最好一起下载。这个源码文件除了对应Mybatis里面jar包的源码以外,还有test文件,即演示版
配置Mybatis
1.导入Mybatis的jar包
mybatis-3.4.6.jar
2.核心配置文件(在源代码的演示文档中找)
核心配置文件Configuration.xml拷贝到工程中
配置好了可以帮我们去加载驱动、连接
核心配置文件,修改为对应的数据库驱动
Configuration.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <!DOCTYPE configuration 4 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 5 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 6 7 <configuration> 8 <settings> 9 <setting name="useGeneratedKeys" value="false"/> 10 <setting name="useColumnLabel" value="true"/> 11 </settings> 12 13 <typeAliases> 14 <typeAlias alias="UserAlias" type="org.apache.ibatis.submitted.complex_property.User"/> 15 </typeAliases> 16 17 <environments default="development"> 18 <environment id="development"> 19 <transactionManager type="JDBC"> 20 <property name="" value=""/> 21 </transactionManager> 22 <dataSource type="UNPOOLED"> 23 <property name="driver" value="com.mysql.jdbc.Driver"/> 24 <property name="url" value="jdbc:mysql://127.0.0.1:3306/micro_message"/> 25 <property name="username" value="root"/> 26 <property name="password" value="123456"/> 27 </dataSource> 28 </environment> 29 </environments> 30 31 <mappers> 32 <mapper resource="org/apache/ibatis/submitted/complex_property/User.xml"/> 33 </mappers> 34 35 </configuration>
这里的<property name="url" value="jdbc:mysql://127.0.0.1:3306/micro_message"/>最好写成
<property name="url" value="jdbc:mysql://127.0.0.1:3306/micro_message?useUnicode=true&characterEncoding=UTF-8"/>
防止出现乱码问题
JDBC中的Dao层
Dao层其实只关心
1.执行SQL语句
2.获取操作结果封装信息
3.返回操作结果
在JDBC的代码,如果执行的是一条预编译的SQL语句,那就必须得通过一个对象为这个SQL语句去设置这些预编译的参数,SqlSession就 具备这样的能力
数据库会话指的就是SqlSession,SqlSession就是一次跟数据库交互的会话
db层:真正和数据库去交互
Mybatis跟JDBC不一样,它不是像JDBC这样把SQL语句写死在代码里面,然后才去执行的,也不是像JDBC一样去用java代码去动态的拼接这个检索条件。
<select id="find" parameterType="long" resultMap="UserResult">
id属性:为sql语句起一个唯一名字,好让java代码里面的SqlSession通过这个名称去调用。id不能重名
<mapper namespace="User">
通过namespace为每个配置文件都起一个不同的名称,那不同的namespace下相同的id是可以存在的,是不冲突的,通过namespace加以区分。
<id column="ID" jdbcType="INTEGER" property="id"/>
jdbcType="INTEGER":数据库里的字段类型与JDBC Types中的类型或者说与这个Types类下面的常量名有一种对应关系
//java.sql.Types
例如 int-->INTEGER
varchar-->VARCHAR
这条sql语句查询出来的列名将在对应关系里找到对应关系,把查出来的这一列的列值放到对应的对象属性里面
第4章 实战第三部 --- 越战越勇
OGNL能从java的对象中去取属性值,而且它能直接调用java对象的方法
log4j.properties:
都是key=value的形式(键值对)
log4j.rootLogger=DEBUG,Console //使用log4j输出日志的时候,输出的级别DEBUG,以及输出的位置Console,大于等于DEBUG级别的输出形式都会被输出;root针对整个工程下面所有输出日志的地方都将会按照这个规定DEBUG,Console来输出
输出级别:由低到高
这里输出级别为什么是DEBUG?
因为Mybatis源码可以看出,其他级别都高于DEBUG,信息就输出不出来
log4j.appender.Console=org.apache.log4j.ConsoleAppender //输出到控制台,起的名字:Console
log4j.appender.Console.layout=org.apache.log4j.PatternLayout //布局方式,按照自己的想法去输出,这里的布局方式是自定义
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n //自定义输出内容的格式,%开头都是有特殊含义的,空格、方括号、减号按原样输出。%d指的是产生日志的时间;%t指的是产生这个日志所处于的那个线程的线程名称;%p输出的日志级别(debug,info,warn,error),%-5p:5指的是至少你输出的字符会占5位字符,不足5位将会用空格补齐,-(负号)指的是补齐的空格在右边,如果没有-(负号),补齐的空格将在左边;%c指的是输出日志时所处于的那个类的全名,包括包名;%m指的是你输出的时候附加的这个信息将会出现在这个位置(例:log.dabug("adf")中的adf);%n指的是换行。
log4j.logger.org.apache=INFO //log4j.logger关键字,不能动;org.apache自己写的包名,写什么包名都行;为某个特定的包下面去配其他不同的级别,org.apache这个包下面的输出级别是INFO,DEBUG信息在这个包下是不输出的,就不影响我们看我们想看的信息
log4j.rootLogger=DEBUG,Console //是针对整个工程的
Mybatis对于各种各样的log都定义好接口了,你加入哪一种log,它就调用哪一种。
控制台输出日志如下:
2018-10-29 12:01:30,268 [http-bio-8080-exec-7] DEBUG [Message.queryMessageList] - ==> Preparing: select ID,COMMAND,DESCRIPTION,CONTENT from MESSAGE where 1=1 and DESCRIPTION like '%' ? '%' //最终执行的sql语句
2018-10-29 12:01:30,269 [http-bio-8080-exec-7] DEBUG [Message.queryMessageList] - ==> Parameters: 精彩(String) //输入的参数
2018-10-29 12:01:30,274 [http-bio-8080-exec-7] DEBUG [Message.queryMessageList] - <== Total: 2 //执行查询有两条结果
4-4 实现单条信息删除
servlet负责接收页面的值,向页面传值,如果有其他业务逻辑需要处理,可以调用相应的service来完成这个的功能
service层就负责接收servlet传过来的值,并对这个值进行处理,做业务的操作、算法等等,如果有需要调用相应的Dao层
Dao层完成与数据库的交互,执行相应的sql语句。
4-5 实现信息批量删除
item指的是迭代出来的某一个具体的项,具体的项如果是一个简单的类型,直接写item就可以,如果是一个对象的话,需要item.属性名,才能把它引用出来
4-6 实现自动回复功能(上)
如果content等于上述几种情况,那么它在if表达式里面判断是为false
5-1 一对多关系的配置 I
select a.ID C_ID,a.NAME,a.DESCRIPTION,b.ID,b.CONTENT,b.COMMAND_ID
from COMMAND a left join COMMAND_CONTENT b
on a.ID=b.COMMAND_ID
left join关联子表,关联条件a.ID=b.COMMAND_ID。当出现两张表的时候,应该取个别名(COMMAND别名为a,COMMAND_CONTENT 别名为b),方便引用,同时也规避了一些问题。
配置一对多关系的目的是将主表的值填充到对应的主表实体类的属性中,并且通过collection标签关联的子表,
<collection property="contentList" resultMap="CommandContent.Content"/>
将子表查询出来的值填充到映射的子表实体类的属性中。
5-3 一对多关系的配置Ⅲ
通过Mybatis帮我们去通过配置文件转换以后,变成一个一对多关系呈现出来的列表
5-4 常用标签
1.where标签
1 <!-- where标签的作用:1.帮我们输出where关键字,类似之前jdbc的sql语句 select ID a,COMMAND,DESCRIPTION,CONTENT from MESSAGE where 2 2.当里面的条件都不满足,没有检索条件时,它自己也不再输出where关键字,变成无条件检索select ID a,COMMAND,DESCRIPTION,CONTENT from MESSAGE 3 3.将整个后面拼出来的检索条件最前面的and或者是or给截掉,让sql语句依然是正确的,可以执行的 4 (例:select ID a,COMMAND,DESCRIPTION,CONTENT from MESSAGE where and COMMAND=#{command} and DESCRIPTION like '%' #{description} '%') 5 就会变成这样:select ID a,COMMAND,DESCRIPTION,CONTENT from MESSAGE where COMMAND=#{command} and DESCRIPTION like '%' #{description} '%' 6 --> 7 <where> 8 <if test="command != null and !"".equals(command.trim())"> 9 and COMMAND=#{command} 10 </if> 11 <if test="description != null and !"".equals(description.trim())"> 12 and DESCRIPTION like '%' #{description} '%' 13 </if> 14 </where>
2.sql标签
<!-- sql标签相当于java里面的我们经常用的常量定义的概念 。起一个名字id="columns"--><sql id="columns">ID,COMMAND,DESCRIPTION,CONTENT</sql>
3.引用sql标签
1 <select id="queryMessageList" parameterType="com.imooc.bean.Message" resultMap="MessageResult"> 2 <!-- 引用sql标签 --> 3 select <include refid="columns"/> from MESSAGE 4 <where> 5 <if test="command != null and !"".equals(command.trim())"> 6 and COMMAND=#{command} 7 </if> 8 <if test="description != null and !"".equals(description.trim())"> 9 and DESCRIPTION like '%' #{description} '%' 10 </if> 11 </where> 12 </select>
4.set变签(相当于set关键字)
上面的逗号加在哪都不合适,不管是哪一个语句在前,最后都会多出来的,set标签就是解决这个问题的。
这里面如果拼的有内容,就输出set关键字,并且把最后结尾的逗号给去掉。和where标签类似
5.trim标签
prefix:前缀
suffix:加在内容的后面输出
当你拼的字符串最前面拼接了and,就帮你去掉
代替where标签
代替set标签
6.choose标签
相当于
if...else if...else if...else
或者是
switch...
case...
case...
case...
default
7.association标签 :用法和connection标签相似
connection标签:在主表上加的,每查询出来一条主表的数据去关联查询它有多少条子数据
相反的,如果查询出来一条子表的数据,希望关联到主表,然后在子表的对象里面能看到主表对象里面的内容。
property指的是在子表对应的实体类里面有一个对应主表实体的引用
这样再用关联查询的时候可以把主表的数据一起关联并且映射到子表对应的实体类里面的属性里面
常用标签归纳
标签名称分别对应sql语句里面增删改查的关键字
因为select标签,查询出来的结果集需要转换成java对象,方便进一步操作,就认识了resutMap标签
可以将结果集中的列与java对象的属性对应起来,并将值填充进去
注意:与java对象对应的列不是数据库里表中的列名,而是查询结果集中的列名
第6章 实战第五部---战斗总结
1 <resultMap type="com.imooc.bean.Message" id="MessageResult"> 2 <id column="ID" jdbcType="INTEGER" property="id"/> 3 <result column="COMMAND" jdbcType="VARCHAR" property="command"/> 4 <result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/> 5 <result column="CONTENT" jdbcType="VARCHAR" property="content"/> 6 </resultMap> 7 8 <select id="queryMessageList" parameterType="com.imooc.bean.Message" resultMap="MessageResult">
这里的resultMap="MessageResult"可以改为resultType=“com.imooc.bean.Message”,当用resultType的时候,就不再需要配置<resultMap></resultMap>标签了,那这样结果集是如何与java类对应的呢?
没有resultMap来表明对应关系了,就只能靠名字,也就是说当结果集中的列名与Message这个类里面的属性名相同的时候,就表示它们之间有映射关系,结果集中的这一列的值就应该放到Message类的属性中,而且这个名称的对应关系是大小写不敏感的。
resultType=“java.util.Map” Mybatis就会自动把结果集放到Map中,key就是结果集中的列名,value是结果集中的值,这样写大小写是敏感的。
resultType缺点:用resultType的时候必须保证结果集中的列名与java类中的属性名相同,用resultMap就没有这个要求,因为resultMap是考标签来配置对应关系的,名称不同它是不受影响的。
在配置resultMap的时候可以通过一个typeHandler属性来做类型转换
parameterMap:表明参数中的属性与数据库中的列对应的关系。目前parameterMap是Mybatis官方不推荐使用的属性,只是为了保持与老版本一致。
看到Map结尾的是映射(要配置映射关系),Type结尾是类型(java的类型)
被Mybatis解析之后
#{}有预编译的效果,反复执行相同的sql语句,如果只是参数不同,有性能上的优势,同时还可以防止sql注入等。一般不会用${}将变量的值直接拼在sql语句里面。
#{}与ognl表达式的取值写法是相同的。