MyBatis
MyBatis的简介:
MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。
MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。
MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录。
MyBatis作为持久层框架,其主要思想是将程序中的大量sql语句剥离出来,配置在配置文件中,实现sql的灵活配置。这样做的好处是将sql与程序代码分离,可以在不修改程序代码的情况下,直接在配置文件中修改sql。
MyBatis的工作原理:
Reader reader =null;
//读取配置信息,生成Reader对象
reader=Resources.getResourceAsReader("Configuration.xml");
//创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sfb=new SqlSessionFactoryBuilder();
//根据SqlSessionFactoryBuilder对象创建SessionFactory
SqlSessionFactory factory =sfb.build(reader);
//创建session对象
SqlSession session = factory.openSession();
session.close();
MyBatis和hibernate:
都从配置文件中得到sessionFactory
从sessionFactory中产生session
通过session完成对数据的增删改
Mybatis的session不安全,用完就要关闭。
不需要管理开启事务,但是要提交事务
也有映射文件
MyBatis的优点:
好学,灵活性好
Hibernate和MyBatis:
Hibernate的移植性好,Dao层开发简单
MyBatis的开发流程:
1、 搭建环境,导入jar 包,配置主配置文件(指定实体类别名,配置数据库信息,配置映射文件)
2、 建立对象模型(对象的实体类以及对象之间的关系:关联属性)
3、 根据对象模型建立数据库中关系模型:使用mybatis需要手动创建数据库,创建表以及主外键设置
4、 定义功能规范:接口
5、 针对接口中不同的方法中在不同的xml文件中编写与方法对应的sql语句
6、 拿到SqlSession对象(手动拿到的是不安全的)
7、 通过session创建实现接口的类的对象
UserMapper userMapper=session.getMapper(User.class);
搭建测试环境:
- Ø MyEclipse 8.5
- Ø mysql 5.1
- Ø jdk 1.6
- Ø apache-tomcat-6.0.14
- Ø mybatis-3.2.2.jar
创建Java项目
导入jar包:
mybatis_HOME/mybatis-3.2.2.jar
mybatis_HOME/lib/*.jar
MySql jdbc驱动:
mysql-connector-java-5.0.4-bin.jar
Junit-3.8.1.jar
定义接口:
MyBatis根据接口自动创建持久层代码
MyBatis的主配置文件:Configuration.xml
<typeAliases >配置别名
配置开发环境
配置数据源(JDBC)
连接池是dbcp连接池
映射文件和实体类的关系不是很密切
Sql语句和接口中的方法对应
<select id=”接口中的名字的方法” parameterType=”接口中的方法参数类型” resultMap=”接口中的方法的返回值类型”>
<?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>
//定义别名
<typeAliases>
<typeAlias alias="IdCard" type="com.mybatis.IdCard"/>
<typeAlias alias="Person" type="com.mybatis.Person"/>
</typeAliases>
//环境配置
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/hibernate_one2one_pk_1" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
//写了接口中方法对应的sql语句的xml文件,一个接口多个方法,可以有多个xml文件
<mappers>
<mapper resource="com/mybatis/IdCard.xml"/>
<mapper resource="com/mybatis/Person.xml"/>
</mappers>
</configuration>
MyBatis不能自己创建表,必须手工创建表。
工具类:
1、 读取配置文件reader=Resources.getResourceAsReader(“Configuration.xml”)
2、 创建SqlSessionFactoryBuilder对象
3、 通过SqlSessionFactoryBuilder对象读取reader创建工厂
SqlSessioFactory factory=ssfb.build(reader);
factory.openSession();//拿到session,线程不安全,用完就要关闭
//创建实现了UserMapper接口的持久类对象(持久层对象)UserMapper是一个定义了方法的接口。
UserMapper userImpl=session.getMapper(UserMapper.class);
1、 session得到相应的User.xml配置文件(因为session是由SqlSessionFactory创建的,读取流主配置信息)
2、 session能找到接口,并且能找到接口中的方法
3、 session能找到与接口中的方法对应的sql语句,按照sql语句自动的实现方法
User user=userImpl.selectUserById(1);//调用接口实现类的方法
#{id}:取出参数名为id对应的参数值
在主配置文件中定义别名,后面的配置中 都可以在别名的基础上写路径。
MyBatis体现了面向接口编程
MyBatis做增删改查
1、 找到对象模型以及对象模型的关系
2、 确定如何操纵数据库
3、 配置xml,是的接口中的每个方法都有对应的sql语句,使用sql语句实现接口中的方法
4、 通过session的getMapper创建实现接口的类的对象
5、 调用对象的相应方法,完成增删改查操作
6、 关闭session
一个接口中定义的方法,可以散布在多个xml配置中
创建sql语句执行
查询所有用户:返回的是List集合
resultMap:自定义返回值类型的集合
<resultMap type="User" id="resultListUser">
<id column="id" property="id" />
<result column="userName" property="userName" />
<result column="userAge" property="userAge" />
<result column="userAddress" property="userAddress" />
</resultMap>
查询出来的记录生成resultListUser所标识的user对象,然后将记录的字段设到User对象中,然后把User对象放入list集合中,继续查下一条,依次生成对象放入list集合。
<!-- 返回list 的select 语句,注意 resultMap 的值是指向前面定义好的 -->
<select id="selectUsers" resultMap="resultListUser">
select * from user
</select>
查询表中的指定字段,设到Map中,再将Map设到list 集合中:
resultSet:指定生成集合
<!-- 把用户的id,userName封装到map集合 -->
<select id="selectMaps" resultType="java.util.HashMap">
select id,userName from user
</select>
从user表中找到相应的字段,生成Map,字段名作为key,字段值作为value,然后将Map设到list集合中。
一条记录创建一个Map,一个Map中有两个Entry(键值对)。
有多少条记录就有多少个Map,查询多少个字段Map中就会有几个Entry键值对。
MyBatis的分页技术:
RowBounds:分页器对象
rowBounds =new RowBounds(”起点:从第几条记录查”,”查几条记录”)
session.selectList(“selectUsers”,null,rowBounds);
缺点:内存使用不当
Mybatis使用内存分页
原理:先查询出所有的记录,然后再查询指定分页查询的记录
插入:(两种插入方式)数据库自动生成主键id:
<insert id="addUser" parameterType="User"
useGeneratedKeys="true" keyProperty="id">
insert into user(userName,userAge,userAddress)
values(#{userName},#{userAge},#{userAddress})
</insert>
#{userName}:从user对象中拿到username属性设定user表中对应的字段上。
useGeneratedKeys="true":Mybatis可以从数据库中取得这个记录的id 设给这个对象的id属性。
keyProperty="id":指定id属性为主键
MyBatis的方法中有多个参数需要传递的时候,需要把对象封装成一个对象,再传递。
resultMap:(手动设定返回值类型的对象)
主键给主键设值的时候 使用id标签
普通属性设值使用result标签
<resultMap type="User" id="resultListUser">
<id column="id" property="id" />
<result column="userName" property="userName" />
<result column="userAge" property="userAge" />
<result column="userAddress" property="userAddress" />
</resultMap>
MyBatis的注重点:
接口怎么定义
接口对应的sql语句怎么写
MyBatis的增删改查的特点:
主键不使用数据库自增:设置主键为手动设定,必须手动添加主键,手动提交数据。
更新数据:先查询再update(和jdbc更新几乎一样)
删除数据:一定要commit
删除后的数据:数据库中没有记录,对象还在:对象状态从持久态变为瞬时态。
多个条件查询:将多个条件封装到一个对象中(Condition对象)
Sql语句:
<select id=”find” parameterType=”Condition” resultType=”Article”>
select * from acticle
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="userid != null">
and userid = #{userid}
</if>
</where>
</select>
增删改查:
<?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="com.mybatis.UserMapper">
<!-- 为了返回list 类型而定义的returnMap -->
<resultMap type="User" id="resultListUser">
<id column="id" property="id" />
<result column="userName" property="userName" />
<result column="userAge" property="userAge" />
<result column="userAddress" property="userAddress" />
</resultMap>
<!-- 返回list 的select 语句,注意 resultMap 的值是指向前面定义好的 -->
<select id="selectUsers" resultMap="resultListUser">
select * from user
</select>
<!-- 把用户的id,userName封装到map集合 -->
<select id="selectMaps" resultType="java.util.HashMap">
select id,userName from user
</select>
<!--执行增加操作的SQL语句。id和parameterType
分别与IUserOperation接口中的addUser方法的名字和
参数类型一致。以#{name}的形式引用Student参数
的name属性,MyBatis将使用反射读取Student参数
的此属性。#{name}中name大小写敏感。引用其他
的gender等属性与此一致。seGeneratedKeys设置
为"true"表明要MyBatis获取由数据库自动生成的主
键;keyProperty="id"指定把获取到的主键值注入
到Student的id属性-->
<insert id="addUser" parameterType="User"
useGeneratedKeys="true" keyProperty="id">
insert into user(userName,userAge,userAddress)
values(#{userName},#{userAge},#{userAddress})
</insert>
<!--执行查询数据的SQL语句-->
<select id="selectUserByID" parameterType="int" resultType="User">
select * from `user` where id = #{id}
</select>
<!--执行更新数据的SQL语句-->
<update id="updateUser" parameterType="User" >
update user set userName=#{userName},userAge=#{userAge},
userAddress=#{userAddress} where id=#{id}
</update>
<!--执行删除数据的SQL语句-->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
</mapper>
PPT:个人介绍,项目介绍,基本技术,基本功能,预期结果
各个版本的源代码
项目评审成绩表
Many-to-one:
对象模型:
User :id ,name,group
Group:id ,name
关系模型:
手动建表:
t_user: id是主键,groupid为外键,外键参照t_group表的主键
t_group:id是主键,没有外键
insert into user(name,groupid) values(#{name},#{group.id})
#{group.id}:group:是User对象的一个属性,group属性所指的Group对象中有id属性。这就是将group属性所指的Group对象的id属性设到groupid字段上。
所以在存储之前,必须先存储group对象,使得Group对象有id。
many-to-one的查询:手动创建sql语句
select t_user.id uid,t_user.name uname ,t_user.groupid
,t_group.name from t_user ,t_group where t_user.groupid=t_group.id and t_groupid=#{id}
#{id}:标识的是对象的属性
查询出来的数据接收:resultMap自定义接收数据类型
<association property=”group” javaType=”Group” resultMap=”resultGroup”/>
association:标识外键
通过结果集生成user对象:三个属性 (id ,name,group)
group为关联属性:Group类型的对象,使用resultMap所标识的标签给group属性设值,相同字段名的值使用别名。
主要步骤:
1、 联合查询找到相应的数据
2、 先生成 User对象(里面有个group属性)
3、 生成Group对象,再设到User对象的group属性上
One-to-one:
对象模型:
Person: id,name,idCard
IdCard: id ,idcardNum
关系模型:
主键就是外键,外键参照idcard属性对应的类所映射的表
Hibernate的唯一主键关联(ont-to-one自动级联)
<id name=”id”>
<generator class=”foreign”>
<param name=”property”>idCard</param>
</generator>
</id>
<one-to-one name=”idCard” constrained=”true”/>
Person对象的id从idcard属性对应的IdCard对象的id中取得
IdCard对象的主键自动生成,IdCard对象一定要拿到id属性,需要标识useGeneratedKeys=”true”,keyProeprty=”id”,因为需要拿到id属性给Person对象的id属性赋值作为主键。
这里不会自动级联,需要手动先存储IdCard 对象然后再存储Person ,Person对象的id赋值 #{idCard.id},通过关联属性所对应的对象的id属性。
insert into t_person(id ,name) values(#{idCard.id},#{name})
session.commit();记得提交事务
然后也要记得关闭session.
加载关系:查找id为1 的记录,生成person对象
id从记录中查到的id赋值,name从记录中查到的name赋值
association: 外键 关联属性的赋值(idCard)
resultMap:
<id property =”id”/>
<result property =”name”/>
<association property=”idCard” javaTpye=” IdCard” resultMap=”resultIdcard” />
property:指定给哪个属性赋值
javaType:指定属性类型
resultMap:指定属性在标识所标识的对象中生成
假若查询语句中使用了别名字段,那么结果集也需要使用别名
select t_person.id pid t_person.name pname from t_person;
<id property =”id” column=”pid”/>
<result property =”name” column =”pname”/>
property:指定对象中的属性名
column:指定数据库中查询出来的字段名
Many-to-many:
对象模型:
Role:id,name
User:id,name,roles(Set)
关系模型:
创建第三张表:至少两个字段userid,roleid,分别参照t_user,t_role
创建三张表:
t_user:id name(id:auto_increment)
t_role:id,name(id:auto_increment)
t_user_role:id,userid,roleid(id:auto_increment,
userid:foreign key,roleid:foreign key)
设置外键:(使用命令行生成)
create table hcheck(
id int (20) primary key,
fkey char(20) not null, //外键设置为学号
constraint fkey foreign key(fkey) references student(ID)
)ENGINE=InnoDB auto_increment=1 Default charset=utf8;
存储关系:
创建对象:
先创建(多个)Role对象,id自动生成
创建User对象user1,id自动生成
创建Set集合,把Role对象设到set集合中
把set集合设到User对象的roles属性中
再创建User对象user2,id自动生成
创建Set集合,把Role对象设到set集合中
把set集合设到User对象的roles属性中
调用方法存储:
调用接口中的方法存储对象
先存储Role对象,再存储User对象
将多个参数封装成一个对象存储:
最后存储UserRole对象
将两个参数封装成一个对象(因为mybatis一次只能存储一个参数)
分别迭代set集合,将存储的对象id迭代取出来,存到UserRole对象中:
new UserRole(u1.getId(),role.getId());
在调用接口实现类的方法时传递UserRole对象,将两个参数以一个对象的方式传递过去。
insert into t_user_role(userid,roleid) values(#{userid},#{roleid})
加载关系:先主找外,再外找主(one-to-many,many-to-one)
创建集合进行关联:
查找id为1的User对象
先把三张表建立关系
连接查询: select * form t_user,t_role,t_user_role where t_user.id=t_user_role.userid and t_role.id=t_user_role.roleid;
<id property=”对象中的属性名” column=”数据库中的字段名:如果设置了别名就写别名”>
<result property=”对象中的属性名” column=”数据库中的字段名:如果设置了别名就写别名”>
给roles属性设值,用的是collection标签
ofType:指定集合中存放的数据类型
<collection property=”roles” ofType=”Role”>
<id property=” id” column=”bid(查询的时候设置的别名)”/>
<result property=”name” column=”username(别名)”/>
</collection>
查到一条数据,就存到roles属性上,依次执行
配置示例:
<?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:这是一个接口,下面的sql语句和接口中的方法一一对应
方法名对应sql语句的id标识
方法参数对应sql语句中的parameterType
方法的返回值对应sql语句中的resultMap/resultType
resultMap:自定义返回值类(主要用于集合,多条语句的查询)
resultType:已存在的返回值类型的对象
-->
<mapper namespace="com.mybatis.Mapper">
<insert id="addRole" parameterType="Role"
useGeneratedKeys="true" keyProperty="id">
insert into t_role(rolename)
values(#{name})
</insert>
<resultMap id="resultRole" type="Role">
<id property="id" column="t_role.id" />
<result property="name" column="rolename" />
</resultMap>
<select id="getRoleByID" parameterType="int" resultMap="resultRole">
select * from `t_role` where id = #{id}
</select>
</mapper>
继承映射:
如何从表中取出相关的记录生成相关的对象
多态查询:父类 Animal ,子类:Bird,Pig
手动建立表,鉴别器字段手动指定
存储:
创建Bird对象,手动设定除主键以外的字段的值
创建Pig对象,手动设定除主键以外的各个字段的值
调用接口实现类对象对应的方法 将对象存储到数据库的表中
insert into t_animal(type,name,sex,weight) values(#{type},#{name},#{sex},#{weight})
加载关系:
完成多态查询:
鉴别器字段的设置:
column:指定字段为鉴别器字段
<discriminator javaType=”string” column=”type”>
<case value=”P” resultType=”Pig”>
<result property=”weight” column=”weight”>
</case>
<case value=”B” resultType=”Bird”>
<result property=”height” column=”height”>
</case>
</discriminator>
最终版本银行项目:
SpringMVC+Spring+MyBatis
AOP完成添加日志,并且添加权限验证(权限表)
管理员可以冻结账户()
SpringMVC+Spring+Mybatis的集成
1、创建web项目
2、导入mybatis的jar包(mybatis的主jar:,mybatis-3.2.2.jar,mybatis-spring-1.2.1.jar,数据库的驱动:mysql-connector-java-3.1-1.bin.jar)
3、配置MyBatis的主配置文件
Web.xml的配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
//SpringMVC的配置信息
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
//Spring的配置
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!--指定Spring 的主配置文件所在目录。默认配置在WEB-INF目录下 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
</web-app>
启动tomcat:
读取web.xml文件,先创建ContextLoaderListener监听器对象,对application内置对象的创建和销毁做监听
全局初始化参数里面封装spring的主配置文件信息
全局初始化参数封装到application内置对象中
Application内置对象一创建,会调用contextInitialized方法,通过事件对象拿到application内置对象,拿到全局初始化参数Spring的配置文件信息,在该方法中创建BeanFactory,然后封装到application内置对象中
BeanFactory一创建:
1、 Spring创建数据源对象dataSource,在数据源中注入数据库的连接信息(url,驱动,用户名,密码)
<!--配数据源本示例采用DBCP连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>mysql</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/ssm</value>
</property>
</bean>
2、通过数据源和MyBatis的配置信息创建SqlSessionFactory对象,注入数据源对象,注入所有的sql语句的配置信息
<property name=”dataSource” ref=”dataSource”/>
<propertyname=”mapperLocation” value=”classpath:cn/ssm/bean/.*xml”/>
<!--配置sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--dataSource属性指定要用到的连接池-->
<property name="dataSource" ref="dataSource"/>
<!--所有实体类的映射文件-->
<property name="mapperLocations" value="classpath:com/tmall/bean/*.xml"/>
</bean>
在myBatis中生成SqlSessionFactory,拿到session对象,用来通过getMapper根据接口生成接口实现类对象
3、配置映射器:生成接口实现类对象(持久对象)
通过sqlSessionFactory和注入接口来创建持久对象
<bean id=”Mapper” class=”Spring的类”>
</bean>
<!--配置映射器-->
<bean id="Mapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!--sqlSessionFactory属性指定要用到的SqlSessionFactory实例-->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
<!--mapperInterface属性指定映射器接口,用于实现此接口并生成映射器对象-->
<property name="mapperInterface" value="com.tmall.inter.OperationMapper" />
</bean>
4、创建业务层对象
<bean id=”loginService” class=”cn.ssm.service.LoginService”/>
5、通过数据源创建配置事务管理器(存储,更新,删除不用提交)
使用spring的类创建事务管理器对象,注入数据源就可以了
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
创建springMVC的中央控制器对象DispatcherServlet,执行init方法,读取主配置文件springmvc-servlet.xml,创建webFactory。
创建视图定位器对象
创建请求分派器对象
配置启用注解,配置扫描的包
请求分派器到指定的包下找后端处理器类(@Controller标识的类),创建后端处理器对象,再继续找@Resource标识的属性,注入相应业务层对象
Spring和Mybatis不需要使用代理,也没有织入方法。和Hibernate不一样。
发送请求:
执行项目以前,手动创建数据库,创建表以及表之间的关系
请求交给Tomcat,Tomcat创建request内置对象接收请求
发现是*.do交给SpringMVC处理,截取请求路径/login.do
到webFacotry找到请求分派器
请求分派器找后端处理器,并且根据请求找到@RequestMapping标识的方法
在对应的方法中调用业务对象的方法处理请求。
将需要存储的对象存入request内置对象中
读取主配置:别名,数据库信息,映射文件信息
今日任务:
1、 把银行项目5.0 ,mystruts1.0,学生管理系统看一遍
2、 把java基础,spring springmvc,struts1,hibernate, mybatis, javaweb基础的文档都看一遍
3、 把用友公司的相关信息了解,然后看相关面试题
4、 数据库相关知识,了解公司产品