mybatis原理
手动创建sqlsessionfactorybuillder对象,由sqlsessionfactorybuillder对象调用build()方法(方法参数是读取到
的mybatis配置文件对象)创建sqlsessionfactory对象,sqlsessionfactory对象调用opensession()方法创建sqlsession
对象,sqlsession对象就可以调用方法(如:selectLest())执行sql语句mapper配置文件中的sql语句。
流程:
- pom文件中添加mybatis依赖。
- mybatis配置文件配置数据库配置信息和sql语句的mapper文件。
- 配置sql语句mapper文件(配置sql语句)
- 主方法文件中创建sqlsessionfactorybuilder对象,sqlsessionfactory对象,sqlsession对象,然后sqlsession对象
执行sql语句mapper中的sql语句。 - 关闭session。
代理与动态代理
使用代理的意义就是以实体为中心的思想。
动态代理,通过sqlSession.getMapper(StudentDao.class)得到StudentDao接口实现类的实例对象,其中StudentDao是数据访问层接口。此时StudentDao接口实现类是框架在运行过程中自动生成,不显示显示,也不用写这个实现类,得到StudentDao接口实现类的实例对象,就可以调用这个实例对象中的方法执行sql语句。
mybatis流程
mybatis 对象
- Resources
- SqlSessionFactoryBuilder
- SqlSessionFactory
- sqlsession
三层架构
1.界面层
2.业务逻辑
3.数据访问
原因
使用JDBC缺陷:
- 代码比较多,开发效率低
- 需要关注 Connection ,Statement, ResultSet 对象创建和销毁
- 对 ResultSet 查询的结果,需要自己封装为 List
- 业务代码和数据库的操作混在一起
MyBatis解决主要问题
- 减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ;
- 不用编写关闭资源代码。
- 直接使用 java 对象,表示结果数据。
- 让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳。
Mybatis可以完成
- 注册数据库的驱动,例如 Class.forName(“com.mysql.jdbc.Driver”))
- 创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象
jdbc
List<Student> list = new ArrayLsit<>();
ResultSet rs = state.executeQuery(“select * from student”);
while(rs.next){
Student student = new Student();
student.setName(rs.getString(“name”));
student.setAge(rs.getInt(“age”));
list.add(student);
ResultSet.close() ;
Statement.close() ;
Conenection.close();
- 从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象
MyBatis 框架原理:
MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。
MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
让开发者专注 SQL的处理
mybatis可以向jdbc类似执行sql语句
//1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
String config="mybatis.xml";
//2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建了SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
//String sqlId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
String sqlId = "com.bjpowernode.dao.StudentDao.selectStudents";
//7. 重要】执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
//8.输出结果
//studentList.forEach( stu -> System.out.println(stu));
for(Student stu : studentList){
System.out.println("查询的学生="+stu);
}
System.out.println("----nihao----");
//9.关闭SqlSession对象
sqlSession.close();
sqlsessionfactory对应连接,sqlsession对应sql语句操作对象。
以业务逻辑dao接口为中心,映射bean对象与表(就是把bean对象与数据库中的表联系起来),这是dao接口的意义。
@Test
public void testSelectStudents(){
StudentDao dao = new StudentDaoImpl();
List<Student> studentList = dao.selectStudents();
for(Student stu:studentList){
System.out.println(stu);
}
}
@Test
public void testInsertStudent(){
StudentDao dao = new StudentDaoImpl();
Student student = new Student();
student.setId(10905);
student.setName("盾山");
student.setEmail("dunshan@qq.com");
int nums = dao.insertStudent(student);
System.out.println("添加对象的数量:"+nums);
}
动态获取单个表执行对象的代理对象
StudentDao dao = sqlSession.getMapper(StudentDao.class);
dao接口向sql语句传参
传参方式;
1. 一个参数
public Student selectStudentById(@Param(“studentId”) Integer id);
where id=${studentId}
dao.selectStudentById(1005);
2.多个参数
List selectMultiParam(@Param(“myname”) String name,
@Param(“myage”) Integer age);
where name=#{myname} or age=#{myage}
3.对象传参
List selectMultiStudent(Student student);
where name=#{name} or age=#{age}
4.位置传参
List selectMultiPosition(String name, Integer age);
where name = #{arg0} or age=#{arg1}
5.map传参
List selectMultiByMap(Map<String, Object> map);
where name = #{myname} or age=#{age1}
返回结果类型
就是执行完sql语句之后,得到的结果类型
- 简单类型
- 对象类型
- list类型
- map类型
注意 返回结果如果是集合,resultType设置为集合包含的类型。
列名和属性名一样
List<Student> selectAllStudents();
<!--使用resultMap
1)先定义resultMap
2)在select标签,使用resultMap来引用1定义的。
-->
<!--定义resultMap
id:自定义名称,表示你定义的这个resultMap
type:java类型的全限定名称
-->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
<!--列名和java属性的关系-->
<!--注解列,使用id标签
column :列名
property:java类型的属性名
-->
<id column="id" property="id" />
<!--非主键列,使用result-->
<result column="name" property="name" />
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
select id,name, email , age from student
</select>
resultMap
针对表字段名与bean属性名不一样的一种设置,主要用于bean属性来自不同的表。
<resultMap id="myStudentMap" type="com.bjpowernode.domain.MyStudent">
<!--列名和java属性的关系-->
<id column="id" property="stuid" />
<!--非主键列,使用result-->
<result column="name" property="stuname" />
<result column="email" property="stuemail" />
<result column="age" property="stuage" />
</resultMap>
<!--列名和属性名不一样:第一种方式-->
<select id="selectMyStudent" resultMap="myStudentMap">
select id,name, email , age from student
</select>
<!--列名和属性名不一样:第二种方式
resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)
-->
<select id="selectDiffColProperty" resultType="com.bjpowernode.domain.MyStudent">
select id as stuid ,name as stuname, email as stuemail , age stuage from student
</select>
模糊查询like
List<Student> selectLikeOne(String name);
<!--第一种 like , java代码指定 like的内容-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like #{name}
</select>
<!--第二种方式:在mapper文件中拼接 like的内容-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like "%" #{name} "%"
</select>
动态sql语句
定义sql片段
<!--定义sql片段-->
<sql id="studentSql">
select id,name, age, email from student
</sql>
<sql id="studentSqlOne">
id,name, age, email
</sql>
sql代码片段, 就是复用一些语法
步骤
1.先定义 <sql id="自定义名称唯一"> sql语句, 表名,字段等 </sql>
2.再使用, <include refid="id的值" />
if及sql片段使用
<!-- if
<if:test="使用参数java对象的属性值作为判断条件,语法 属性=XXX值">
-->
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
select <include refid="studentSqlOne" /> from student
where id > 0
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
where
<!--
where: <where> <if> <if>...</where>
-->
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql" />
<where>
<if test="name !=null and name !='' ">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
foreach
foreach使用1
<select id="selectForeachOne" resultType="com.bjpowernode.domain.Student">
select * from student where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</select>
foreach使用2
<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql" /> where id in (
<foreach collection="list" item="stu" >
#{stu.id},
</foreach>
-1 )
</select>
<foreach collection="" item="" open="" close="" separator="">
#{xxx}
</foreach>
collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
item:自定义的,表示数组和集合成员的变量
open:循环开始是的字符
close:循环结束时的字符
separator:集合成员之间的分隔符
查询所有
<!--查询所有-->
<select id="selectAll" resultType="com.bjpowernode.domain.Student">
select * from student order by id
</select>
mybatis主配置文件
- 定义别名
- 数据源
- mapper 文件
<?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>
<!--指定properties文件的位置,从类路径根开始找文件-->
<properties resource="jdbc.properties" />
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--定义别名-->
<typeAliases>
<!--
第一种方式:
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<!--<typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
<typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />-->
<!--
第二种方式
<package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
-->
<package name="com.bjpowernode.domain"/>
<package name="com.bjpowernode.vo"/>
</typeAliases>
<!--配置插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
<environments default="mydev">
<environment id="mydev">
<!--
transactionManager:mybatis提交事务,回顾事务的方式
type: 事务的处理的类型
1)JDBC : 表示mybatis底层是调用JDBC中的Connection对象的,commit, rollback
2)MANAGED : 把mybatis的事务处理委托给其它的容器(一个服务器软件,一个框架(spring))
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
数据源表示Connection对象的。
type:指定数据源的类型
1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
3)JNDI:java命名和目录服务(windows注册表)
-->
<dataSource type="POOLED">
<!--数据库的驱动类名-->
<property name="driver" value="${jdbc.driver}"/>
<!--连接数据库的url字符串-->
<property name="url" value="${jdbc.url}"/>
<!--访问数据库的用户名-->
<property name="username" value="${jdbc.user}"/>
<!--密码-->
<property name="password" value="${jdbc.passwd}"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
<!--第一种方式:指定多个mapper文件-->
<!--<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<mapper resource="com/bjpowernode/dao/OrderDao.xml" />-->
<!--第二种方式: 使用包名
name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
使用package的要求:
1. mapper文件名称需要和接口名称一样, 区分大小写的一样
2. mapper文件和dao接口需要在同一目录
-->
<package name="com.bjpowernode.dao"/>
<!-- <package name="com.bjpowernode.dao2"/>
<package name="com.bjpowernode.dao3"/>-->
</mappers>
</configuration>
**
mybatis 主要思想是围绕数据库进行,使用流程主要是配置好mybatis文件后,数据访问层方法向mapping文件传参,及对mapping配置文件中sql语句接收参数、返回结果、sql语句的编辑。
**