一、 课程安排
1. EJB框架
(EJB重量级持久层,天然分布式,负载均衡) 但是不够灵活,不能充分适应业务。多条件查询,如果使用EntityBean,做查询时,一种查询条件就得写一个sql。SessionBean
新增,修改,删除交给EntityBean;多条件查询交给SessionBean。
2. 【面试】hibernate和mybatis区别
Hibernate,java面向对象盛行时期,将整个开发设计过程全部面向对象开发,全ORM。
iBatis,维持原有的编程方式,前面部分按面向对象思考和设计,持久层时使用sql语句,面向过程。
1) 底层仍然使用sql,将hql语句转为sql。Sql无法优化
2) Hibernate通过反射,性能很低
3) Ibatis就是基于jdbc轻量级封装,还是使用sql。性能比较高。半ORM
二、 MyBatis介绍
MyBatis 世界上流行最广泛的SQL 映射框架,由ClintonBegin 在2002 年创建,iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。其后,捐献给了Apache基金会,成立了iBatis 项目。2010 年5 月,将代码库迁致Google Code,并更名为MyBatis。
1. Hibernate和mybatis比较
三、 初体验
1. 开发步骤
a) 创建Web项目
b) 导入jarMybatis3.2.2
mybatis-3.2.2.jar 核心驱动
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-log4j12-1.7.5.jar
mysql-connector-java-5.1.26.jar 数据库驱动
c) 核心配置sqlMapConfig.xml
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置数据源,事务 -->
<environmentsdefault="test">
<environmentid="test">
<!--事务:JDBC/MANAGED-自己管理去 -->
<transactionManagertype="JDBC"/>
<!--数据源:POOLED/UNPOOLED/JNDI -->
<dataSourcetype="POOLED">
<propertyname="driver" value="com.mysql.jdbc.Driver"/>
<propertyname="url"value="jdbc:mysql://localhost:3306/mybatisdb?charsetEncoding=utf8"/>
<propertyname="username" value="root"/>
<propertyname="password" value="root"/>
</dataSource>
</environment>
<environmentid="deploy">
<!--事务:JDBC/MANAGED-自己管理去 -->
<transactionManagertype="JDBC"/>
<!--数据源:POOLED/UNPOOLED/JNDI -->
<dataSourcetype="POOLED">
<propertyname="driver" value="com.mysql.jdbc.Driver"/>
<propertyname="url"value="jdbc:mysql://localhost:3306/mybatisdb?charsetEncoding=utf8"/>
<propertyname="username" value="root"/>
<propertyname="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--映射文件mapper -->
</configuration>
d) 测试类SqlSessionFactoryBuilder.builer()创建一个SqlSessionFactory
package test;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月15日
*/
public class TestMybatis {
@Test
publicvoid init() throws IOException{
Stringresource = "sqlMapConfig.xml";
InputStreamis = Resources.getResourceAsStream(resource);
SqlSessionFactoryfactory = new SqlSessionFactoryBuilder().build(is);
SqlSessionsession = factory.openSession();
}
}
e) 通过SqlSessionFactory获取SqlSession,可以调用CRUD操作。
f) 创建数据库表
g) 映射文件mapper
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 配置命名空间,区别名称 -->
<mappernamespace="cn.itcast.mapper.PersonMapper">
<!--查询,注意Mybatis中如果有填写集合类型,只填写集合中元素的类型 -->
<selectid="find" resultType="cn.itcast.domain.Person">
select* from person
</select>
</mapper>
h) 测试
package test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import cn.itcast.domain.Person;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月15日
*/
public class TestMybatis {
@Test
publicvoid init() throws IOException{
Stringresource = "sqlMapConfig.xml";
InputStreamis = Resources.getResourceAsStream(resource);
SqlSessionFactoryfactory = new SqlSessionFactoryBuilder().build(is);
SqlSessionsession = factory.openSession();
//如何访问mapper中的方法呢? 规则:命名空间+.+id
List<Person>personList =session.selectList("cn.itcast.mapper.PersonMapper.find");
System.out.println(personList.size());
for(Personp : personList){
System.out.println(p);
}
}
}
2. SqlSessionFactory和SqlSession
SqlSessionFactory它是一个线程安全
SqlSession 它是不安全
3. 参数
parameterMap 废除,它是ibatis
parameterType
4. 获取SQL中的参数
#name# ibatis
#{}, ${} mybatis
注意selectOne时,结果集必须是一条记录,否则mybatis报错
org.apache.ibatis.exceptions.TooManyResultsException:Expected one result (or null) to be returned by selectOne(), but found: 3
<!--查询一个,按id查询 -->
<selectid="get"parameterType="int"resultType="cn.itcast.domain.Person">
select * from person
</select>
@Test//查询一条
publicvoidtestGet(){
SqlSession session = factory.openSession();
Person p = session.selectOne("cn.itcast.mapper.PersonMapper.get", 1);
System.out.println(p);
}
5. 当数据库表字段和实体对象属性名称不一致时,怎么处理?
解决办法:
1)通过sql的字段命名别名,别名跟实体对象属性一致
select id,user_name as name,age,remark fromperson
Mybatis它对象映射是通过结果集的字段名称
2) Mybatis最强大功能 resultMap对象
6. 结果集
resultType 基础类型,int,string,Person
resultMap 针对resultMap标签
7. 获取SqlSessionFactory
private SqlSessionFactoryfactory;
@Before //最先执行,初始化SessionFactory
publicvoid init()throws IOException{
String resource = "sqlMapConfig.xml";
InputStream is = Resources.getResourceAsStream(resource);
factory =new SqlSessionFactoryBuilder().build(is);
}
四、 业务CRUD实现
1. 新增
<insertid="insert"parameterType="cn.itcast.domain.Person">
insert into person
(id,user_name,age,remark)
values
(#{id},#{name},#{age},#{remark})
</insert>
@Test //新增
publicvoid testInsert(){
SqlSessionsession = factory.openSession();
Personp = new Person();
p.setId(4);
p.setName("hellen");
p.setAge(16);
p.setRemark("xijiang");
session.insert("cn.itcast.mapper.PersonMapper.insert",p);
session.commit(); //提交事务
System.out.println("insertfinished.");
}
2. 修改
<updateid="update"parameterType="cn.itcast.domain.Person">
update person
set user_name=#{name},age=#{age},remark=#{remark}
where id = #{id}
</update>
publicvoid testUpdate(){
SqlSessionsession = factory.openSession();
Personp = new Person();
p.setId(4);
//p.setName("hellen2");
p.setAge(18);
//p.setRemark("beijing");
session.update("cn.itcast.mapper.PersonMapper.update",p);
session.commit();
}
3. 删除一条
<deleteid="deleteById" parameterType="int">
deletefrom person
whereid = #{pid}
</delete>
publicvoid testDeleteById(){
SqlSessionsession = factory.openSession();
session.delete("cn.itcast.mapper.PersonMapper.deleteById",4);
session.commit();
}
4. 删除多条,整形数组
<deleteid="delete" parameterType="int">
deletefrom person
whereid in
<foreachcollection="array" item="id" open="("close=")" separator=",">
#{id}
</foreach>
</delete>
@Test //删除多条-数组
publicvoid testDeleteByArray(){
SqlSessionsession = factory.openSession();
int[]ids = {4,6};
session.delete("cn.itcast.mapper.PersonMapper.deleteArray",ids);
session.commit();
}
<!--删除多条,LIST集合 -->
<deleteid="deleteList"parameterType="int">
delete from person
where id in
<foreachcollection="list"item="id"open="("close=")"separator=",">
#{id}
</foreach>
</delete>
5. 删除多条-LIST
publicvoid testDeleteByList(){
SqlSession session = factory.openSession();
List<Integer>_list =new ArrayList<Integer>();
_list.add(4);
_list.add(6);
session.delete("cn.itcast.mapper.PersonMapper.deleteList", _list);
session.commit();
}
6. 删除多条,Map
<deleteid="deleteMap" parameterType="int">
deletefrom person
whereid in
<foreachcollection="map" item="id" open="("close=")" separator=",">
#{id}
</foreach>
</delete>
7. 删除多条,Map , ids 代表map中key
<deleteid="deleteMap" parameterType="map">
deletefrom person
whereid in
<foreachcollection="ids" item="id" open="(" close=")"separator=",">
#{id}
</foreach>
</delete>
@Test //删除多条 MAP
publicvoid testDeleteByMap(){
SqlSessionsession = factory.openSession();
Map<String,Object>paraMap = new HashMap<String,Object>();
int[]ids = {4,6};
paraMap.put("ids",ids);
session.delete("cn.itcast.mapper.PersonMapper.deleteMap",paraMap);
session.commit();
}
8. 获取记录总数
<selectid="count"resultType="int">
SELECT COUNT(*) FROM person
</select>
@Test //获取记录总数
publicvoid testCount(){
SqlSessionsession = factory.openSession();
inti = session.selectOne("cn.itcast.mapper.PersonMapper.count");
System.out.println(i);
}
9. 简化
1) 别名
<!--起别名 -->
<typeAliases>
<typeAliastype="cn.itcast.domain.Person"alias="Person"/>
</typeAliases>
<!--查询一个,按id查询 -->
<selectid="get" parameterType="int"resultType="Person">
select* from person
whereid = #{pid}
</select>
2) SQL片段
<sqlid="cols">id,user_name,age,remark</sql>
<selectid="find" resultMap="personRM">
select<include refid="cols"/> from person
</select>
传参:map和po对象实体,查询条件封装
例如:年龄(整数),出生日期,入职日期(日期)
日期,有开始时间,结束时间
Map随意构造
10. 动态SQL语句
1) <where> 能自动去掉where最前面and或者or
<selectid="find"parameterType="map"resultMap="personRM">
select <include refid="cols"/> from person
<where>
<iftest="name!=null">and user_name like#{name}</if>
<iftest="age!=null">and age=#{age}</if>
</where>
</select>
2) <set>自动删除最后一个逗号
<set>
<iftest="name!=null">user_name=#{name},</if>
<iftest="age!=null">age=#{age},</if>
<iftest="remark!=null">remark=#{remark},</if>
</set>
3) <foreach>
<foreachcollection="ids" item="id" open="("close=")" separator=",">
#{id}
</foreach>
whereid in
(
<foreachcollection="array" item="id" separator=",">
#{id}
</foreach>
)
五、 对象关联
1. 对一,需求:人员可以有扩展信息
人员person
扩展person_info 拓展用户信息,例如
人员和扩展信息表一对一
在mybatis中关联关系只有两种
对一<association property=""></association>,
对多<collection property=""></collection>
结果集中有重名字段。
如果发生这种情况,重名情况,Mybatis,拿一个id字段的值,放到setId内。
如何处理?
赋别名
1) 配置文件PersonInfoMapper.xml
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="cn.itcast.mapper.PersonInfoMapper">
<resultMaptype="cn.itcast.domain.Person" id="personInfoRM">
<idproperty="id" column="ID"/>
<resultproperty="name" column="USER_NAME"/>
<resultproperty="age" column="AGE"/>
<resultproperty="remark" column="REMARK"/>
</resultMap>
<!--使用继承方式,配置对一关联关系 -->
<resultMaptype="cn.itcast.domain.Person" id="personPersonInfoRM"extends="personInfoRM">
<associationproperty="personInfo"javaType="cn.itcast.domain.PersonInfo">
<idproperty="id" column="INFOID"/>
<resultproperty="station" column="STATION"/>
<resultproperty="joinDate" column="JOIN_DATE"/>
</association>
</resultMap>
<!--查询,人员和人员扩展信息 -->
<selectid="findPersonInfo" parameterType="map"resultMap="personPersonInfoRM">
SELECT
p.id,p.user_name,p.age,p.remark,
i.idAS infoid,i.station,i.join_date
FROM
(SELECT id,user_name,age,remark FROMperson) p
LEFT JOIN
(SELECT id,station,join_date FROMperson_info) i
ON p.id=i.id
<where>
<iftest="name!=null">user_name=#{name}</if>
</where>
</select>
</mapper>
2) 客户端调用
package test;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.itcast.domain.Person;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月15日
*/
public class TestPersonInfo {
privateSqlSessionFactory factory;
@Before //最先执行,初始化SessionFactory
publicvoid init() throws IOException{
Stringresource = "sqlMapConfig.xml";
InputStreamis = Resources.getResourceAsStream(resource);
factory= new SqlSessionFactoryBuilder().build(is);
}
@Test //查询管理的一对一
publicvoid testPersonInfo(){
SqlSessionsession = factory.openSession();
Mapmap = new HashMap();
List<Person>personList =session.selectList("cn.itcast.mapper.PersonInfoMapper.findPersonInfo",map);
for(Personp : personList){
System.out.println(p);
}
}
}
2. 对多,人员可以拥有多本书籍
需求,某个人有几本书
package cn.itcast.domain;
1) Book实体
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月15日
*/
public class Book {
privateInteger id;
privateString name;
privateDouble money;
publicInteger getId() {
returnid;
}
publicvoid setId(Integer id) {
this.id= id;
}
publicString getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
publicDouble getMoney() {
returnmoney;
}
publicvoid setMoney(Double money) {
this.money= money;
}
}
2) 改造person对象
package cn.itcast.domain;
import java.util.List;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月15日
*/
public class Person {
privatePersonInfo personInfo; //对一关联
privateList<Book> books; //对多关联
privateInteger id;
privateString name;
privateInteger age;
privateString remark;
publicInteger getId() {
returnid;
}
publicvoid setId(Integer id) {
this.id= id;
}
publicString getName() {
returnname;
}
publicvoid setName(String name) {
this.name= name;
}
publicInteger getAge() {
returnage;
}
publicvoid setAge(Integer age) {
this.age= age;
}
publicString getRemark() {
returnremark;
}
publicvoid setRemark(String remark) {
this.remark= remark;
}
publicPersonInfo getPersonInfo() {
returnpersonInfo;
}
publicvoid setPersonInfo(PersonInfo personInfo) {
this.personInfo= personInfo;
}
publicList<Book> getBooks() {
returnbooks;
}
publicvoid setBooks(List<Book> books) {
this.books= books;
}
}
3) 对多,配置
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="cn.itcast.mapper.PersonInfoMapper">
<resultMaptype="cn.itcast.domain.Person" id="personInfoRM">
<idproperty="id" column="ID"/>
<resultproperty="name" column="USER_NAME"/>
<resultproperty="age" column="AGE"/>
<resultproperty="remark" column="REMARK"/>
</resultMap>
<!--使用继承方式,配置对一关联关系 -->
<resultMaptype="cn.itcast.domain.Person" id="personPersonInfoRM"extends="personInfoRM">
<associationproperty="personInfo"javaType="cn.itcast.domain.PersonInfo">
<idproperty="id" column="INFOID"/>
<resultproperty="station" column="STATION"/>
<resultproperty="joinDate" column="JOIN_DATE"/>
</association>
</resultMap>
<!--使用继承方式,配置对多的关联关系 -->
<resultMaptype="cn.itcast.domain.Person" id="personBookRM"extends="personPersonInfoRM">
<collectionproperty="books" ofType="cn.itcast.domain.Book">
<idproperty="id" column="BOOK_ID"/>
<resultproperty="name" column="BOOK_NAME"/>
<resultproperty="money" column="MONEY"/>
</collection>
</resultMap>
<!--查询,人员和人员扩展信息 -->
<selectid="findPersonInfo" parameterType="map"resultMap="personPersonInfoRM">
SELECT
p.id,p.user_name,p.age,p.remark,
i.idAS infoid,i.station,i.join_date
FROM
(SELECT id,user_name,age,remark FROMperson) p
LEFT JOIN
(SELECT id,station,join_date FROMperson_info) i
ON p.id=i.id
<where>
<iftest="name!=null">user_name=#{name}</if>
</where>
</select>
<!--查询某个人的人员信息,(扩展信息,书籍) -->
<selectid="findPersonInfoBook" parameterType="map"resultMap="personBookRM">
SELECT
p.id,p.name,p.age,p.remark,
p.infoid,p.station,p.join_date,
b.book_id,b.book_name,b.money
FROM
(
SELECT
p.id,p.name,p.age,p.remark,
i.infoid,i.station,i.join_date
FROM
(SELECTid,user_name AS NAME,age,remark FROM person) p
LEFTJOIN
(SELECTid AS infoid,station,join_date FROM person_info) i
ONp.id=i.infoid
) p
LEFT JOIN
(SELECTid AS book_id,NAME AS book_name,money,person_id FROM book) b
ON p.id=b.person_id
</select>
</mapper>
4) 客户端调用
@Test //查询某个人员(人员和人员信息的一对一,人员和书籍的一对多
publicvoid testPersonBook(){
SqlSessionsession = factory.openSession();
Mapmap = new HashMap();
List<Person>personList = session.selectList("cn.itcast.mapper.PersonInfoMapper.findPersonInfoBook",map);
System.out.println(personList.size());
}
某个用户的书籍
3. SQL优化
缩小中间结果集
Select p.*,info.*,book.* from person leftjoin person_info left join book on…..
1) 视图
在做大型项目,视图可能废除。项目组不允许在项目中使用视图
2) Hibernate
它在中小型项目中使用,无法SQL优化。
六、 知识回顾
1) log4j日志没有显示
配置环境升级jdk1.6升级为jdk1.7;(log4j-1.2.17.jar)
2) mybatis作用
持久层框架
特点:半自动ORM映射,将数据库中的数据封装到对象中
3) 怎么获得mybatis?
SqlSessionFactory 线程安全性
SqlSession 线程非安全,不能做类的公用变量
4)Mybatis核心配置文件sqlMapConfig.xml
配置内容:
1) 配置事务
2) 配置数据源
3) 声明mapper文件
5)Mapper文件
1) 命名空间,在不同的mapper,但mapper中的方法同名,靠命名空间区分
2) resultMap不是必须,可以不写,前提:表和实体的属性一样。(mybatis底层自动生成resultMap)
3) 它通过数据结果集来映射的。Hibernate它是通过数据库表字段来映射的。
4) 关联关系:
A.对一association javaType
B.对多collection ofType
jdbcType
它是指定当NAME为null时,给jdbc驱动程序告诉它,它针对的数据库字段的类型。(Oracle)
<updateid="update" parameterType="cn.itcast.domain.Person">
updateperson
<set>
<iftest="name!=null">user_name=#{name,jdbcType=VARCHAR},</if>
<iftest="age!=null">age=#{age},</if>
<iftest="remark!=null">remark=#{remark},</if>
</set>
whereid = #{id}
</update>
6)Mapper中写SQL
获取参数
#{} 它会自动根据参数类型做封装。例如对字符串类型,两边加单撇;对整数类型直接使用;好处防止SQL注入(推荐)
${} 将用户填入的参数直接拼接到SQL。(字符串直接拼接)坏处:SQL注入;例如:拼接orderby条件(特殊的地方)
7)SQL中含有特殊字符
<if test="ageEnd!=null"><![CDATA[and age <=]]> #{ageEnd}</if>
8)动态SQL
<if> 判断条件
<where> 自动删除最前面的and 或者or,实际开发中常用where1=1
<set> 它自动删除最后一个set值的逗号,修改时,修改参数不同
<foreach> 主要应用在in子查询,批量删除时候,array,list,map
9)常规的标签
<select> 查询,参数map;返回值List(selectList),可以是一个值(selectOne)
<insert> 新增,参数po;新增时习惯写所有的字段
<update> 修改,参数po;修改时习惯使用动态sql语句
<delete> 删除,参数 int,string,array,list,map
10)参数:
A. parameterMap 废除,早期使用
B. parameterType 简单变量int/string/double/po/map
11)返回值:
A. resultType 简单变量int/string/double/po/map
B. resultMap 它是mybatis核心;实际resultType使用时,底层自动转为resultMap;在数据库结果集和实体对象加了一层。例如:数据库字段USER_NAME,实体中name;通过它mybatis可以找到映射的规则;它可以配置关联关系;mybatis自动将大大的结果集分拆到各个对象中。(难点)
SQL返回的结果集中字段不能有重名的,如果有,必须设置别名,通过resultMap映射时进行转化。
12)类中调用mybatis
sqlSession提供很多方法
selectList 查询多条,返回结果集封装到List
selectOne 查询一条,必须返回一个值,如果不是,报错;
insert 新增
update 修改
delete 删除
13)两种调用形式:
A. 不带参数,命名空间+.+id
B. 带参数,命名空间+.+id,封装到对应mapper中声明的类型
七、 高级应用
1. 接口开发
使用sqlsession提供selectList…,它们调用方式不习惯,它命名空间.id,如果字母写错,在编译时无法提示。运行报错。
通过命名空间找的mapper文件,在通过id去找到一个具体sql去执行。
1) 规则:
1) 接口名称必须和mapper文件名称相同
2) 接口包路径和命名空间一致(接口文件和mapper文件在一起)
3) 接口中要声明的方法名和某个sql配置的id属性一致
4) 参数和返回值,要按java规则写
package cn.itcast.mapper;
import java.util.List;
import java.util.Map;
import cn.itcast.domain.Person;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
public interface PersonMapper {
publicList<Person> find(Map map);
publicPerson get(Integer id);
publicvoid insert(Person person);
publicvoid update(Person person);
publicvoid deleteById(Integer id);
publicvoid deleteList(List list);
publicvoid deleteMap(Map map);
publicInteger count();
}
2) 调用:面向对象的开发方式(推荐)
package test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.itcast.domain.Person;
import cn.itcast.mapper.PersonMapper;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
public class TestMapperInterface {
privateSqlSessionFactory factory;
@Before //最先执行,初始化SessionFactory
publicvoid init() throws IOException{
Stringresource = "sqlMapConfig.xml";
InputStreamis = Resources.getResourceAsStream(resource);
factory= new SqlSessionFactoryBuilder().build(is);
}
@Test
publicvoid testFind(){
SqlSessionsession = factory.openSession();
//获取接口对象
PersonMappermapper = session.getMapper(PersonMapper.class);
Mapmap = new HashMap();
map.put("name","'t%'");
List<Person>pList = mapper.find(map);
System.out.println(pList.size());
}
@Test
publicvoid testGet(){
SqlSessionsession = factory.openSession();
PersonMappermapper = session.getMapper(PersonMapper.class);
Personp = mapper.get(1);
System.out.println(p.getName());
}
@Test
publicvoid testInsert(){
SqlSessionsession = factory.openSession();
PersonMappermapper = session.getMapper(PersonMapper.class);
Personp = new Person();
p.setId(4);
p.setName("tom");
p.setAge(8);
mapper.insert(p);
session.commit();
}
@Test
publicvoid testUpdate(){
SqlSessionsession = factory.openSession();
PersonMappermapper = session.getMapper(PersonMapper.class);
Personp = mapper.get(4);
p.setAge(9);
mapper.update(p);
session.commit();
}
@Test
publicvoid testDeleteById(){
SqlSessionsession = factory.openSession();
PersonMappermapper = session.getMapper(PersonMapper.class);
mapper.deleteById(4);
session.commit();
}
@Test
publicvoid testDeleteList(){
SqlSessionsession = factory.openSession();
PersonMappermapper = session.getMapper(PersonMapper.class);
List<Integer>list = new ArrayList();
list.add(5);
list.add(6);
mapper.deleteList(list);
session.commit();
}
@Test
publicvoid testDeleteMap(){
SqlSessionsession = factory.openSession();
PersonMappermapper = session.getMapper(PersonMapper.class);
Mapmap = new HashMap();
map.put("ids",new Integer[]{4,5,6,7});
mapper.deleteMap(map);
session.commit();
}
@Test
publicvoid testCount(){
SqlSessionsession = factory.openSession();
PersonMappermapper = session.getMapper(PersonMapper.class);
inti = mapper.count();
System.out.println(i);
}
}
2. Mybatis自动生成映射文件和PO对象和调用示例代码工具
1) 安装myeclipse插件
2) 配置文件:
可以随意放在任何一个工程中,它可以通过配置指向要生成的工程
在配置文件中自己指定当前环境中的驱动jar
工具如果再次生成会覆盖之前的内容
3) 优点:
大量减少写代码的工作量,代码比较规范。
日常就拷贝insert,update,delete和字段;实体
4) 缺点:
关联关系它不会生成,手工修改;
项目组的规范不同,手工修改;
生成的example内容都要手工清除
3. 缓存
一级缓存Hibernate,session级别
二级缓存Hibernate,sessionFactory级别
Mybatis它和hibernate一样
1) 一级缓存:
@Test//一级缓存
publicvoidcacheLevel1(){
SqlSession session = factory.openSession();
PersonMapper mapper = session.getMapper(PersonMapper.class);
Map map = newHashMap();
map.put("name","'tony'");
List<Person> personList = mapper.find(map);
System.out.println(personList.size());
PersonMapper mapper2 = session.getMapper(PersonMapper.class);
List<Person> personList2 = mapper2.find(map);
System.out.println(personList2.size());
}
2) 二级缓存
默认Mybatis二级缓存不开启,
如何开启
使用
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 配置命名空间,区别名称 -->
<mappernamespace="cn.itcast.mapper.PersonMapper">
<!--使用二级缓存 -->
<cache/>
@Test//二级缓存
publicvoidcacheLevel2(){
SqlSession session = factory.openSession();
PersonMapper mapper = session.getMapper(PersonMapper.class);
Map map = newHashMap();
map.put("name","'tony'");
List<Person> personList = mapper.find(map);
System.out.println(personList.size());
session.close(); //关闭session
session = factory.openSession();
PersonMapper mapper2 = session.getMapper(PersonMapper.class);
List<Person> personList2 = mapper2.find(map);
System.out.println(personList2.size());
}
3) 【面试】二级缓存怎么优化
参数配置
在实际开发中,经过在线上压力测试,找到一个符合当前客户运行环境下最恰当的值。
默认mybatis二级缓存一般
4) 第三方Ehcache
第三方cache中有两个佼佼者;
Ehcache 单机
Momeycache 集群
<cachetype="org.mybatis.caches.ehcache.EhcacheCache"/>
修改为ehcache.xml即可
拦截器interceptor
Mybatis 分页
1) 自定义一个拦截器类,实现interceptor接口
2) 插件,在sqlMapConfig.xml中配置
<?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">
<configuration>
<!--分页拦截器,拦截用户提交的查询,只查询当前页数据;提高响应速度。 -->
<plugins>
<plugininterceptor="cn.itcast.jk.pagination.PageInterceptor">
<propertyname="databaseType" value="oracle"/>
</plugin>
</plugins>
</configuration>
Springmvc 性能监控
开发步骤:
1、编写拦截器,记录Controller方法执行时间
package cn.itcast.jk.interceptor;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.springframework.core.NamedThreadLocal;
importorg.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
*@Description:
*@Author: nutony
*@Company: http://java.itcast.cn
*@CreateDate: 2014-3-6
*/
public class TimerInterceptor implementsHandlerInterceptor {
privateNamedThreadLocal<Long> startTimeThreadLocal = newNamedThreadLocal<Long>("WatchExecuteTime");
publicboolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Objectarg2) throws Exception {
longbeginTime = System.currentTimeMillis(); //开始时间
startTimeThreadLocal.set(beginTime);
returntrue;
}
publicvoid afterCompletion(HttpServletRequest req, HttpServletResponse res, Objectarg2, Exception arg3) throws Exception {
longendTime = System.currentTimeMillis();
longexecuteTime = endTime - startTimeThreadLocal.get();
System.out.println(String.format("%sexecute %d ms." , req.getRequestURI() , executeTime));
}
publicvoid postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Objectarg2, ModelAndView arg3) throws Exception {
}
}
2、在springmvc-servlet.xml文件中配置拦截器
对多个controller进行指定方法的拦截
<mvc:interceptors>
<mvc:interceptor>
<mvc:mappingpath="/cargo/export/list.action"/>
<beanclass="cn.itcast.jk.interceptor.TimerInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mappingpath="/cargo/packinglist/list.action"/>
<beanclass="cn.itcast.jk.interceptor.TimerInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
对多个controller的所有方法拦截
<mvc:interceptors>
<mvc:interceptor>
<mvc:mappingpath="/cargo/export/*"/>
<beanclass="cn.itcast.jk.interceptor.TimerInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mappingpath="/cargo/packinglist/*"/>
<beanclass="cn.itcast.jk.interceptor.TimerInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
对某目录下的controller进行拦截
<mvc:interceptors>
<mvc:interceptor>
<mvc:mappingpath="/cargo/**"/>
<beanclass="cn.itcast.jk.interceptor.TimerInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
拦截整个项目的所有controller
<mvc:interceptors>
<mvc:interceptor>
<mvc:mappingpath="/**"/>
<beanclass="cn.itcast.jk.interceptor.TimerInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
八、 SSM框架实现业务
Springmvc+spring+hibernate
Springmvc+spring+mybatis
开发步骤:
1) 画草图
2) 创建表
3) 创建web工程
4) 导入jar,mybatis包,spring(springmvc),数据库驱动…
aopalliance-1.0.jar
asm-3.3.1.jar
cglib-2.2.2.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
commons-lang3-3.1.jar
commons-logging-1.1.1.jar
ehcache-core-2.6.5.jar
freemarker-2.3.19.jar
javassist-3.11.0.GA.jar
junit-4.9.jar
log4j-1.2.16.jar
mybatis-3.2.2.jar
mybatis-ehcache-1.0.2.jar
mybatis-spring-1.2.0.jar
mysql-connector-java-5.1.10-bin.jar
ognl-3.0.6.jar
slf4j-api-1.6.2.jar
slf4j-log4j12-1.6.2.jar
spring-aop-3.2.2.jar
spring-beans-3.2.2.jar
spring-context-3.2.2.jar
spring-core-3.2.2.jar
spring-expression-3.2.2.jar
spring-jdbc-3.2.2.jar
spring-orm-3.2.2.jar
spring-tx-3.2.2.jar
spring-web-3.2.2.jar
spring-webmvc-3.2.2.jar
5) 创建PO实体对象
package cn.itcast.ssm.domain;
import java.io.Serializable;
import java.util.List;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月15日
*/
public class Person implements Serializable{
privateInteger id;
privateString name;
privateInteger age;
privateString remark;
publicInteger getId() {
returnid;
}
publicvoid setId(Integer id) {
this.id= id;
}
publicString getName() {
returnname;
}
publicvoid setName(String name) {
this.name= name;
}
publicInteger getAge() {
returnage;
}
publicvoid setAge(Integer age) {
this.age= age;
}
publicString getRemark() {
returnremark;
}
publicvoid setRemark(String remark) {
this.remark= remark;
}
}
6) 创建mapper映射文件
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="cn.itcast.ssm.mapper.PersonMapper">
<resultMaptype="cn.itcast.ssm.domain.Person" id="personRM">
<idproperty="id" column="ID"/>
<resultproperty="name" column="USER_NAME"/>
<resultproperty="age" column="AGE"/>
<resultproperty="remark" column="REMARK"/>
</resultMap>
<!--带条件查询 -->
<selectid="find" parameterType="map"resultMap="personRM">
select* from person
where1=1
<iftest="name!=null"> and user_name like #{name}</if>
<iftest="ageStart!=null"> and age>#{ageStart}</if>
<iftest="ageEnd!=null"><![CDATA[ andage<=#{ageEnd}]]></if>
</select>
</mapper>
7) 创建Mapper接口
package cn.itcast.ssm.mapper;
import java.util.List;
import java.util.Map;
import cn.itcast.ssm.domain.Person;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
public interface PersonMapper {
publicList<Person> find(Map map);
}
8) 创建PersonDao接口
package cn.itcast.ssm.dao;
import java.util.List;
import java.util.Map;
import cn.itcast.ssm.domain.Person;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
public interface PersonDao {
publicList<Person> find(Map map);
}
9) 创建PersonDaoImpl
package cn.itcast.ssm.dao.impl;
import java.util.List;
import java.util.Map;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.mybatis.spring.support.SqlSessionDaoSupport;
importorg.springframework.stereotype.Repository;
import cn.itcast.ssm.domain.Person;
import cn.itcast.ssm.mapper.PersonMapper;
/**
*@Description:PersonDao
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
@Repository
public class PersonDaoImpl extendsSqlSessionDaoSupport {
/*
* mybatis3.0.0+mybatis-psring1.0.0无需,整合包自己注入
* mybatis3.2.2+mybatis-spring1.2.0 必须自己注入sqlSessionFactory;
*/
publicvoid setSqlSessiionFactory(SqlSessionFactory sqlSessiionFactory) {
super.setSqlSessionFactory(sqlSessiionFactory);
}
publicList<Person> find(Map map){
PersonMappermapper = this.getSqlSession().getMapper(PersonMapper.class);
returnmapper.find(map);
}
}
10) 创建PersonService接口
package cn.itcast.ssm.service;
import java.util.List;
import java.util.Map;
import cn.itcast.ssm.domain.Person;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
public interface PersonService {
publicList<Person> find(Map map);
}
11) 创建PersonServiceImpl
package cn.itcast.ssm.service.impl;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
importorg.springframework.stereotype.Service;
import cn.itcast.ssm.dao.PersonDao;
import cn.itcast.ssm.domain.Person;
import cn.itcast.ssm.service.PersonService;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
@Service
public class PersonServiceImpl implementsPersonService {
@Resource
PersonDaopersonDao;
publicList<Person> find(Map map){
returnpersonDao.find(map);
}
}
12) 创建PersonController
package cn.itcast.ssm.web.controller;
import java.util.List;
import javax.annotation.Resource;
importorg.springframework.stereotype.Controller;
import org.springframework.ui.Model;
importorg.springframework.web.bind.annotation.RequestMapping;
import cn.itcast.ssm.domain.Person;
import cn.itcast.ssm.service.PersonService;
/**
*@Description:
*@Author: 传智播客 java学院 陈子枢
*@Company: http://java.itcast.cn
*@CreateDate: 2014年11月17日
*/
@Controller
public class PersonController {
@Resource
PersonServicepersonService;
//查询,将查询结果传递到页面
@RequestMapping("/person/list.action") //Controller加载时会自动创建访问路径/person/list;/person/list.action
publicString list(Model model){
List<Person>personList = personService.find(null);
model.addAttribute("personList",personList); //传递到页面
return"/person/jPersonList.jsp";
}
}
13) 创建列表页面jPersonList.jsp
<%@ page language="java"import="java.util.*" pageEncoding="UTF-8"%>
<%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'jPersonList.jsp' starting page</title>
</head>
<body>
人员列表<br>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>备注</td>
</tr>
<c:forEach items="personList"var="p" varStatus="status">
<tr>
<td>${status.index+1}</td>
<td>${p.name}</td>
<td>${p.age}</td>
<td>${p.remark}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
14) 配置sqlMapConfig.xml
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
15) 配置beans.xml
<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!--1.包扫描,service dao -->
<context:component-scanbase-package="cn.itcast.ssm.dao,cn.itcast.ssm.service"/>
<!--2.jdbc.properties属性配置文件 -->
<context:property-placeholderlocation="classpath:jdbc.properties"/>
<!--3.数据源 DataSource -->
<beanid="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName" value="${jdbc.driverclass}"/>
<propertyname="url" value="${jdbc.url}"/>
<propertyname="username" value="${jdbc.username}"/>
<propertyname="password" value="${jdbc.password}"/>
</bean>
<!--4.SqlSessionFactory -->
<beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
<propertyname="dataSource" ref="dataSource"/>
<!--spring和mybatis整合 -->
<!--1)引入mybatis核心配置文件 -->
<propertyname="configLocation" value="classpath:sqlMapCongfig.xml"/>
<!--2)扫描指定目录下的所有Mapper.xml -->
<propertyname="mapperLocations"value="classpath:cn/itcast/ssm/mapper/*.xml"/>
</bean>
<!--5.事务 -->
<beanid="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource" ref="dataSource"/>
</bean>
<tx:adviceid="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:methodname="save*" propagation="REQUIRED"/>
<tx:methodname="insert*" propagation="REQUIRED"/>
<tx:methodname="update*" propagation="REQUIRED"/>
<tx:methodname="delete*" propagation="REQUIRED"/>
<tx:methodname="find*" read-only="true"/>
<tx:methodname="get*" read-only="true"/>
<tx:methodname="view*" read-only="true"/>
<tx:methodname="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcutexpression="execution(* cn.itcast.ssm.service.*.*(..))"id="pointCut"/>
<aop:advisoradvice-ref="txAdvice" pointcut-ref="pointCut"/>
</aop:config>
</beans>
16) 配置springmvc-servlet.xml
<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--1.包扫描controller -->
<context:component-scanbase-package="cn.itcast.ssm.web.controller"/>
<!--2.内部资源视图解析器 -->
<beanid="jspViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="prefix" value="/WEB-INF/pages"/>
<propertyname="suffix" value=""/>
</bean>
</beans>
17) 配置web.mxl
<?xml version="1.0"encoding="UTF-8"?>
<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"version="3.0">
<!--1.spring容器 listener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--2.springmvc servlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!--3.spring 中文乱码 filter -->
<!--编码过滤器,解决中文乱码 -->
<filter>
<filter-name>SpringEncoding</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>SpringEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
18) 发布,测试