1 mybatis别名(掌握)
<typeAliases>
<!-- a)内置别名
常用基本类型 和包装类型 8 个 以及集合类型
-->
<!-- b)自定义别名(1)单独配置类的实现
<typeAlias type="cn.itsource.mybatis.query.ProductQuery" alias="productQuery"></typeAlias>
<typeAlias type="cn.itsource.mybatis.domain.Product" alias="product"></typeAlias>-->
<!-- (2)配置包形式 推荐-->
<package name="cn.itsource.mybatis.query"></package>
<package name="cn.itsource.mybatis.domain"></package>
</typeAliases>
2 映射器Mapper(练习掌握)
昨天:IProductDao(接口) – ProductDaoImpl 实现
今天: ProductMapper(接口) -->不写实现 (mybatis底层会采用动态代理模式 会跟我生成实现)
步骤:
(1) 创建项目 配置mybatis-config.xml 和昨天一样
(2) 创建接口 ProductMapper (XXXXMapper) 里面定义一个方法findAll -->以前dao层/mapper层
(3) 在对应的ProductMapper.xml namespace 和
标签里面id (namespace+id) == (ProductMapper包路径+方法)
<?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 namespace="cn.itsource._01_mapper.mapper.ProductMapper">
<select id="findAll" resultType="product">
select * from product
</select>
</mapper>
(4) 测试类 测试Mapper
@Test
public void testMapper(){
//得到mapper --映射器 (动态代理)
ProductMapper productMapper = MybatisUtil.INSTANCE.getSqlSession().
getMapper(ProductMapper.class);
for (Product product : productMapper.findAll()) {
System.out.println(product);
}
}
3 高级查询注意事项(掌握)
(1)错误写法:
<if test="productName != null">
and productName like '%#{productName}%'
</if>
正确写法: --存在sql注入问题
<if test="productName != null">
and productName like '%${productName}%'
</if>
正确写法:
<if test="productName != null">
and productName like concat('%',#{productName},'%')
</if>
(2)特殊符号转义:
<!-- salePrice minPrice 和maxPrice之间 特殊符号需要转义-->
<!-- <if test="minPrice != null and maxPrice != null">
and salePrice > #{minPrice} and salePrice < #{maxPrice}
</if>-->
<if test="minPrice != null and maxPrice != null">
<![CDATA[
and salePrice > #{minPrice} and salePrice <= #{maxPrice}
]]>
</if>
4 结果映射(掌握)
处理数据库里面的列 和 对象里面的字段 不一统一的情况下
(1)使用别名就可以解决
<select id="findAll" resultType="product">
select id,productName pName,salePrice,costPrice,cutoff from product
</select>
(2)返回Map解决映射问题
<select id="findAll" resultMap="productMap">
select id,productName,salePrice,costPrice,cutoff from product
</select>
<resultMap id="productMap" type="product">
<!-- id:主键
property:类里面的属性
column:查询列名称
-->
<id property="id" column="id"></id>
<result property="pName" column="productName"></result>
<result property="salePrice" column="salePrice"></result>
</resultMap>
5 关系处理(掌握)
5.1 关系
一对一 : 一个身份证对 一个人 一夫一妻 qq 和qq空间
一对多: 一个老师 对应多个学生 / 产品分类 对应多个产品 / 1个部门对应多个员工
多对一: 和一对多 相反
多对多: 多个老师 对应多个学生 (一对多或者多对一组合情况)
用户 和 角色
角色和权限
mybatis怎么处理关系:
一对一 :mybatis处理一方
多对一:mybatis处理一方
多对多: mybatis处理多方
一对多:mybatis处理多方
5.2 对一方处理(多对一/一对一)
嵌套结果: 只发送一条sql
嵌套查询: 发送 1+n条sql
<?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 namespace="cn.itsource._03_manytoone.mapper.ProductMapper">
<!-- <resultMap id="productMap" type="product">
<id column="id" property="id"></id>
<result column="productName" property="pName"></result>
<result column="salePrice" property="salePrice"></result>
<result column="costPrice" property="costPrice"></result>
<result column="cutoff" property="cutoff"></result>
<!– 处理一方–>
<association property="dir" javaType="productDir">
<id column="did" property="id"></id>
<result column="dname" property="dirName"></result>
</association>
</resultMap>-->
<!-- (1)嵌套结果 发送一条sql语句-->
<!-- <select id="findAll" resultMap="productMap">
SELECT
p.id,
p.productName,
p.salePrice,
p.costPrice,
p.cutoff,
dir.id did,
dir.dirName dname
FROM
product p
JOIN productDir dir ON p.dir_id = dir.id
</select>-->
<!-- 嵌套查询:发送多sql语句(1+n条sql)-->
<select id="findAll" resultMap="productMap">
SELECT
p.id,p.productName,p.salePrice, p.costPrice,p.cutoff,p.dir_id
FROM product p
</select>
<resultMap id="productMap" type="product">
<id column="id" property="id"></id>
<result column="productName" property="pName"></result>
<result column="salePrice" property="salePrice"></result>
<result column="costPrice" property="costPrice"></result>
<result column="cutoff" property="cutoff"></result>
<!--根据上面查询dir_id 在去查询 分类对象-->
<association property="dir" column="dir_id" javaType="productDir" select="selectDir">
</association>
</resultMap>
<select id="selectDir" parameterType="long" resultType="ProductDir">
select * from productDir where id = #{dir_id}
</select>
</mapper>
5.3 对多方进行处理(一对多/多对多)
嵌套结果和前台查询
<?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 namespace="cn.itsource._04_onetomany.mapper.ProductDirMapper">
<!-- 嵌套结果-->
<!-- <select id="findAll" resultMap="productDirMap">
select dir.id ,dir.dirName,
p.id pid,p.productName pName,p.salePrice,p.costPrice,p.cutoff
from productDir dir join product p
on dir.id = p.dir_id
</select>
<resultMap id="productDirMap" type="productDir">
<id property="id" column="id"></id>
<result property="dirName" column="dirName"></result>
<collection property="products" ofType="product">
<id property="id" column="pid"></id>
<result property="pName" column="pName"></result>
<result property="salePrice" column="salePrice"></result>
<result property="costPrice" column="costPrice"></result>
</collection>
</resultMap>-->
<!-- 嵌套查询-->
<select id="findAll" resultMap="productDirMap">
select dir.id ,dir.dirName from productDir dir
</select>
<resultMap id="productDirMap" type="productDir">
<id property="id" column="id"></id>
<result property="dirName" column="dirName"></result>
<collection property="products" column="id" ofType="product" select="selectProducts">
</collection>
</resultMap>
<select id="selectProducts" parameterType="long" resultType="product">
select id,productName pName,salePrice,costPrice,cutoff
from product where dir_id = #{dir_id}
</select>
</mapper>
5.4 延迟加载–了解
使用的时候,才去加载内容
product.jsp -->展示所有的产品 把产品的分类展示
以后常用项目模式都是前台端分离模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SCEz8wtf-1577694357382)(笔记.assets/image-20191226141539943.png)]
5.5 缓存-了解
mybatis 支持缓存 (一级缓存 和二级缓存)
redis(nosql的数据库 做缓存)
5.5.1 mybatis一级缓存
属于sqlSession级别缓存(entityManager类似)
命中条件:
mybatis一级缓存 命中(同一个SqlSessionFactory 同一个SqlSession 同一个ID)
public void testMapper(){
//得到mapper --映射器 (动态代理)
SqlSession sqlSession1 = MybatisUtil.INSTANCE.getSqlSession();
//mybatis一级缓存 命中(同一个SqlSessionFactory 同一个SqlSession 同一个ID)
ProductMapper mapper1 = sqlSession1.getMapper(ProductMapper.class);
System.out.println(mapper1.findOne(19L));
ProductMapper mapper2 = sqlSession1.getMapper(ProductMapper.class);
System.out.println(mapper2.findOne(19L));
}
5.5.2 mybatis二级缓存
命中条件: 同一个SqlSessionFactory 不同的SqlSession 同一个ID
什么叫序列化: 把对象转换成二进制的信息 这个过程
为什么需要序列化: 用在网络传输
反序列化:把二进制内容转成对象的形式 这个过程
6 SSM整合(掌握)
现在开发 基本都是很多框架整合起来进行开发
常用开发框架整合:
sss – springmvc+spring+springjdbc (项目一)
sssdj – springmvc+spring+springdatajpa(项目二) 中小型的项目
ssm – springmvc+spring+mybatis(项目三/项目四) 中型项目/大型项目
6.1 整合步骤
(1)创建项目–web项目 (maven/普通web)
(2)导入三个框架的jar包
(3)配置文件
applicationContext.xml --配置spring+mybatis
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
">
<!--扫描service 自动注入到spring service注解 -->
<context:component-scan base-package="cn.itsource.ssm.service"></context:component-scan>
<!-- db.proproperties dataSource sqlSessionFactory transaction mapper-->
<!--引入jdbc.properties-->
<context:property-placeholder location="classpath:db.properties" />
<!--创建dataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mapperLocations" value="classpath:cn/itsource/ssm/mapper/*Mapper.xml"></property>
<property name="typeAliasesPackage">
<value>
cn.itsource.ssm.domain
</value>
</property>
</bean>
<!-- 把产生mapper 交给 spring-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.itsource.ssm.mapper"></property>
</bean>
<!--事务配置-->
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--开启事务注解的支持,默认会去找一个名称叫做transactionManager的事务管理器 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
applicationCotnext-mvc.xml --配置springmvc
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描controller-->
<context:component-scan base-package="cn.itsource.ssm.web.controller" />
<!--静态资源处理-->
<mvc:default-servlet-handler />
<!--识别@RequestMapping等注解支持-->
<mvc:annotation-driven />
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
db.properties --配置库
web.xml --配置web的内容
log4j.properties
7 小扩展(掌握)
7.1 扩展1
<resultMap id="productMap" type="product">
<id column="id" property="id"></id>
<result column="productName" property="pName"></result>
<result column="salePrice" property="salePrice"></result>
<result column="costPrice" property="costPrice"></result>
<result column="cutoff" property="cutoff"></result>
<!-- 处理一方-->
<!--<association property="dir" javaType="productDir">
<id column="did" property="id"></id>
<result column="dname" property="dirName"></result>
</association>-->
<!-- 扩展1-->
<result property="dir.id" column="did"></result>
<result property="dir.dirName" column="dname"></result>
</resultMap>
7.2 扩展2
分页 一对多使用 嵌套结果去分页 ,存在小问题
<select id="findAll" resultMap="productDirMap">
select dir.id ,dir.dirName,
p.id pid,p.productName pName,p.salePrice,p.costPrice,p.cutoff
from productDir dir join product p
on dir.id = p.dir_id
limit 0,2
</select>
<resultMap id="productDirMap" type="productDir">
<id property="id" column="id"></id>
<result property="dirName" column="dirName"></result>
<collection property="products" ofType="product">
<id property="id" column="pid"></id>
<result property="pName" column="pName"></result>
<result property="salePrice" column="salePrice"></result>
<result property="costPrice" column="costPrice"></result>
</collection>
</resultMap>
建议使用嵌套查询:
<select id="findAll" resultMap="productDirMap">
select dir.id ,dir.dirName from productDir dir limit 0,2
</select>
<resultMap id="productDirMap" type="productDir">
<id property="id" column="id"></id>
<result property="dirName" column="dirName"></result>
<collection property="products" column="id" ofType="product" select="selectProducts">
</collection>
</resultMap>
<select id="selectProducts" parameterType="long" resultType="product">
select id,productName pName,salePrice,costPrice,cutoff
from product where dir_id = #{dir_id}
</select>
8常见错误
*11.1********写的mapper文件没有在配置文件里面注册*
java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.itsource.mybatis.crud.UserMapper.createTable
配置找不到方法
*11.2********返回的结果是List,而需要的是一个对象*
org.apache.ibatis.executor.ExecutorException: Statement returned more than one row, where no more than one was expected.
Product findAll()
<select id="findAll"
resultType="cn.itsource.mybatis.c_manytoone.Dept" parameterType="long">
select id,name from t_dept where id=#{id}
</select>
11.3 *没有序列化异常*
使用缓存,如果报序列化问题,让类去实现序列化接口
implements Serializable
9 什么是序列化–面试题
把java对象转换二进制过程
什么情况下使用序列化
1、在网络中直接传输一个java对象。
2、在数据库的Blob(二进制)字段(列)中,直接存一个java对象会出问题
3、当前,需要把java对象放入内存(本地的临时文件)中
java.io.ObjectInputStream
java.io.ObjectOutputStream
4.HttpSession里面存放对象,tomcat的内存不足(500M)的时候,钝化到硬盘