1、Mybatis别名
内置别名
常用基本类型、包装类型、集合类型
自定义别名
第一种形式:直接配置类
<typeAlias type="cn.itsource.mybatis.query.ProductQuery"
alias="productQuery"></typeAlias>
<typeAlias type="cn.itsource.mybatis.domain.Product"
alias="product"></typeAlias>
第二种形式:配置包名(推荐使用)
<typeAliases>
<package name="cn.itsource.mybatis.query"></package>
<package name="cn.itsource.mybatis.domain"></package>
</typeAliases>
2、映射器
ProductMapper(接口)不写实现类,Mybatis底层采用动态代理模式 自动实现
(1)创建项目
(2)创建ProductMapper接口,定义抽象方法
package cn.itsource._01Mapper.mapper;
import cn.itsource._01Mapper.domain.Product;
import java.util.List;
public interface ProductMapper {
List<Product> findAll();
}
(3)在对应的ProductMapper.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 namespace="cn.itsource._01Mapper.mapper.ProductMapper">
<select id="findAll" resultType="product">
select * from product
</select>
</mapper>
(4)测试接口方法
@Test
public void testQuery(){
//映射器
ProductMapper productMapper = myBatisUtil.INTANCE.getSqlSession().
getMapper(ProductMapper.class);
List<Product> all = productMapper.findAll();
for (Product product : all) {
System.out.println(product);
}
}
3、高级查询(模糊查询)
<select id="findByQuery" parameterType="productQuery" resultType="product">
select * from product
<where>
这种方式存在sql注入问题
<!-- <if test="productName!=null">
and productName like '%${productName}%'
</if>-->
最佳写法(推荐)
<if test="productName!=null">
and productName like concat('%',#{productName},'%')
</if>
<!--<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>
</where>
</select>
4、结果映射
解决数据表的列和对象的字段不统一的情况
方案一:取别名就可以解决
<select id="findAll" resultType="product">
select id,productName pName,salePrice,costPrice,cutoff from product
</select>
方案二:返回Map解决映射问题
<mapper namespace="cn.itsource._02result.mapper.ProductMapper">
<!--结果映射处理-->
<select id="findAll" resultMap="productMap">
select id,productName,salePrice,costPrice,cutoff from product
</select>
<!--
id:主键
property:类里面的属性
column:查询列名称
-->
<resultMap id="productMap" type="product">
<id property="id" column="id"></id>
<result property="pName" column="productName"></result>
<result property="salePrice" column="salePrice"></result>
</resultMap>
</mapper>
5、关系处理
关系
一对一:一个主管对应一个部门
一对多:一个部门对应多个员工
多对一:多个员工对应一个部门
多对多:用户角色 角色权限
处理一方
(多对一/一对多)
<resultMap id="productMap" type="product">
<id property="id" column="id"></id>
<result property="pName" column="productName"></result>
<result property="salePrice" column="salePrice"></result>
<result property="costPrice" column="costPrice"></result>
<result column="cutoff" property="cutoff"></result>
<!--方式一 嵌套结果 发送一条sql语句-->
<!--<association property="productDir" javaType="productDir">
<id column="did" property="id"></id>
<result column="dname" property="dirName"></result>
</association>-->
<!--方式二-->
<result property="productDir.id" column="did"></result>
<result property="productDir.dirName" column="dname"></result>
<!--嵌套查询 发送多条sql语句-->
<!-- <association property="productDir" 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 namespace="cn.itsource._04one2many.mapper.ProductMapper">
<!--结果映射处理-->
<!-- 一对多的嵌套结果会有一个问题:查询结果是子集合分类而不是查询结果集合分类-->
<select id="findAll" resultMap="productDirMap">
select dir.id ,dir.Name 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>
</mapper>
Mybatis缓存
一级缓存
默认开启
属于sqlSession级别缓存(entityManager类似)
命中条件:
mybatis一级缓存 命中(同一个SqlSessionFactory 同一个SqlSession 同一个ID)
@Test
public void testMapper(){//一级缓存
//得到mapper --映射器 (动态代理)
SqlSession sqlSession = myBatisUtil.INTANCE.getSqlSession();
//mybatis一级缓存 命中(同一个SqlSessionFactory 同一个SqlSession 同一个ID)
ProductMapper mapper1 = sqlSession.getMapper(ProductMapper.class);
System.out.println(mapper1.findOne(19L));
ProductMapper mapper2 = sqlSession.getMapper(ProductMapper.class);
System.out.println(mapper2.findOne(19L));
}
二级缓存
需要开启条件 1、在ProductMapper.xml中配置cache 2、序列化对应的doamin
命中条件: 同一个SqlSessionFactory 不同的SqlSession 同一个ID
@Test
public void testSecondCacheMapper(){//二级缓存
//得到mapper --映射器 (动态代理)
SqlSession sqlSession1 = myBatisUtil.INTANCE.getSqlSession();
//mybatis一级缓存 命中(同一个SqlSessionFactory 同一个SqlSession 同一个ID)
ProductMapper mapper1 = sqlSession1.getMapper(ProductMapper.class);
System.out.println(mapper1.findOne(19L));
sqlSession1.close();
SqlSession sqlSession2 = myBatisUtil.INTANCE.getSqlSession();
ProductMapper mapper2 = sqlSession2.getMapper(ProductMapper.class);
System.out.println(mapper2.findOne(19L));
sqlSession2.close();
}
ProductMapper.xml配置cache
<mapper namespace="cn.itsource._05cache.mapper.ProductMapper">
<select id="findOne" parameterType="long" resultType="product">
select id,productName pName,salePrice,costPrice,cutoff from product
where id = #{id}
</select>
<!--开启二级缓存需要的配置-->
<cache></cache>
</mapper>
序列化Product(实现Serializable接口)
public class Product implements Serializable{
}
6、扩展
扩展一
处理一方的第二种方式
<resultMap id="productMap" type="product">
<id property="id" column="id"></id>
<result property="pName" column="productName"></result>
<result property="salePrice" column="salePrice"></result>
<result property="costPrice" column="costPrice"></result>
<result column="cutoff" property="cutoff"></result>
<!--方式一 处理一方-->
<!--<association property="productDir" javaType="productDir">
<id column="did" property="id"></id>
<result column="dname" property="dirName"></result>
</association>-->
<!--方式二 相当于直接把查询出来的列的值直接赋给属性对象的属性-->
<result property="productDir.id" column="did"></result>
<result property="productDir.dirName" column="dname"></result>
</resultMap>
扩展二
解决一对多查询存在的小问题
<mapper namespace="cn.itsource._04one2many.mapper.ProductMapper">
<!--结果映射处理-->
<!-- 一对多的嵌套结果会有一个问题:查询结果是子集合分类而不是查询结果集合分类-->
<!--<select id="findAll" resultMap="productDirMap">
select dir.id ,dir.Name 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>-->
<!--解决嵌套查询结果的问题,相当于先分页查询分类,然后再根据分类id查询相应产品-->
<select id="findAll" resultMap="productDirMap">
select dir.id ,dir.name 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>
</mapper>
7、ssm集成
常用开发框架整合:
sss – springmvc+spring+springjdbc (项目一)
sssdj – springmvc+spring+springdatajpa(项目二) 中小型的项目
ssm – springmvc+spring+mybatis(项目三/项目四) 中型项目/大型项目
ssm框架整合步骤
(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
">
<!--扫描包-->
<context:component-scan base-package="cn.itsource.ssm.service"></context:component-scan>
<!--引入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/domain/*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 />
<!--开启注解支持-->
<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>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--spring核心-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--springMvc核心控制器-->
<servlet>
<servlet-name>dispatchServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatchServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--编码过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
db.properties
(配置数据库连接信息)
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis
jdbc.username=test
jdbc.password=123
log4j.properties
(配置日志信息)
log4j.rootLogger=ERROR, stdout
#log4j.rootLogger=NONE
log4j.logger.cn.itsource=TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n