Mybatis使用及原理解析

MyBatis 是一个基于Java的持久层框架。它提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。

MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJO(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录

每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder从一个xml配置文件或者一个预定义的配置类的实例获得配置信息。

 
使用:

1准备资源

1.1数据库中建立相应的表

CREATE DATABASE mybatis;
USE mybatis;
CREATE TABLE tb_user(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(16),
	age INT
	);
INSERT INTO tb_user(NAME, age) VALUES('phf1', 12);
INSERT INTO tb_user(NAME, age) VALUES('phf2', 20);
INSERT INTO tb_user(NAME, age) VALUES('phf3', 30);

1.2 jar包

 

2.在eclipse中测试使用

 

2.1导入jar包。

 
 

2..2建一个mybatis-config.xml配置文件

可以在工程的src目录下
<?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">
  <!--  XML 配置文件包含对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源和 决定事务范围和控制的事务管理器. -->
<configuration>
	<settings>
		 <setting name="cacheEnabled" value="true"/>
  		 <setting name="lazyLoadingEnabled" value="true"/>
	</settings>
	<!-- 给对象取别名  -->
	<typeAliases>
		<typeAlias alias="User" type="org.phf.pojo.User"/>
		<typeAlias alias="Student" type="org.phf.pojo.Student"/>
		<typeAlias alias="Clazz" type="org.phf.pojo.Clazz"/>
	</typeAliases>
	<!-- 配置JDBC连接参数 -->
	<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/mybatis"/>
			      <property name="username" value="root"/>
			      <property name="password" value="root"/>
			</dataSource>
		</environment>
	</environments>
	<!-- 指明每个关系表的配置文件 -->
	<mappers>
		<mapper resource="org/phf/mapping/UserMapper.xml"/>
		<mapper resource="org/phf/mapping/ClazzMapper.xml"/>
     	 	<mapper resource="org/phf/mapping/StudentMapper.xml"/>
	</mappers>
</configuration>

2.3 为封装SqlSessionFactory建个单例


package org.phf.factory;

import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MybatisFactory {
	/**
	 * SqlSessionFactory对象可以看成DataSource(数据库连接池)
	 * 在应用执行期间,应该只创建一次,建议使用单例模式
	 * 通过SqlSessionFactoryBuilder来获得数据库配置参数并创建 
	 */
	private static SqlSessionFactory sqlSessionFactory;
	
	/**
	 * SqlSession对象可以理解成对Connection的封装,即一个数据连接会话
	 * 它同时也封装了连接和断开过程,提供sql语句的映射
	 * SqlSession实例不能被共享,它不是线程安全的。
	 * 所以应该一次性用完后要确保使用finally块来关闭它,关闭时会被收回SqlSessionFactory所管理的连接池中
	 */
	//private static SqlSession session;
	static
	{
		try {
			String resource = "mybatis-config.xml";
			InputStream is = Resources.getResourceAsStream(resource);
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
			System.out.println(sqlSessionFactory);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//
	public static SqlSession getSqlSession()
	{
		return sqlSessionFactory.openSession();
	}
	//
	public static void close(SqlSession session)
	{
		if(session != null)
			session.close();
	}
}
 

2.4为每个表建一个映射类

package org.phf.pojo;
/**
 * 数据库表的映射类,每个实例对象映射到表中的一行数据
 * 属性的名称和类型对应表中字段名和类型,并提供getter和setter方法
 * @author Administrator
 */
public class User {
 private Integer id;
 private String name;
 private Integer age;
 
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Integer getAge() {
  return age;
 }
 public void setAge(Integer age) {
  this.age = age;
 }
 @Override
 public String toString() {
  return "User [id=" + id + ", name=" + name + ", age=" + age + "]\n";
 }

}


2.5建XXXmapper.xml文件和XXXmapper.java接口文件

创建每个表映射类创建的XXXmapper.xml配置文件,并创建相应XXXmapper接口(即数据存取接口),mapper配置文件和接口文件放在同一包目录下
<!-- UserMapper.xml -->
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
 "mybatis-3-mapper.dtd">
<!-- MyBatis 真正的力量是在映射语句中。这里是奇迹发生的地方。
对于所有的力量,SQL 映射的 XML 文件是相当的简单。
当然如果你将它们和对等功能的 JDBC 代码来比较,你会 发现映射文件节省了大约 95%的代码量。
MyBatis 的构建就是聚焦于 SQL 的,使其远离于 普通的方式。Mybatis封装处理了连接和查询结果获取 -->
<mapper namespace="org.phf.mapping.UserMapper">

	<!--开启缓存-->
  <cache />  
	<!-- 
	select 查询语句是使用 MyBatis 时最常用的元素之一。
	id(方法)是 get, parameterType(参数类型)是Integer, resultType(返回类型)是 User对象,其属性就是列名,值是列对应的值。
	 -->
  <select id="find" parameterType="Integer" resultType="User">
  	SELECT * FROM TB_USER WHERE ID = #{id}
  </select>
  <!--单条数据返回类型可以是HashMap,key为列名,value为值 -->
  <select id="findMap" parameterType="Integer" resultType="HashMap">
  	SELECT * FROM TB_USER WHERE ID = #{id}
  	</select>
	
  <!-- 返回多条数据时会自动封装成List集合返回-->
  <select id="findAll" resultType="User">
  	SELECT * FROM TB_USER 
  </select>
  
    <!-- 最多接受一个参数,所以多个参数可以封装成对象传参,可进行判断处理-->
  <select id="findWithIf" parameterType="User" resultType="User">
  	SELECT * FROM TB_USER 
	<where>
		<if test="name!= null">name = #{name}</if>
		<if test="age!= null">and age = #{age}</if>
	</where>
  </select>
    <!-- 多个键值对参数也可以用map传参,key对应列名-->
  <select id="findByNameAndAge" parameterType="Map" resultType="User">
  	SELECT * FROM TB_USER 
	<where>
		<if test="name!= null">name = #{name}</if>
		<if test="age!= null">and age = #{age}</if>
	</where>
  </select>
    <!-- 多个单值参数也可以用List传参,循环处理-->
  <select id="findWithIn" parameterType="list" resultType="User">
  	SELECT * FROM TB_USER WHERE id IN
	<foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
 	</foreach>
  </select>
    <!-- 多个单值参数也可以用List传参,循环处理-->
  <select id="findWithLike" parameterType="String" resultType="User">
  	<bind name="pattern" value="'%' + _parameter + '%'" />
  	SELECT * FROM tb_user 
  	WHERE name LIKE #{pattern}
  </select>
  
</mapper>

//UserMapper.java
package org.phf.mapping;

import java.util.List;
import java.util.Map;

import org.phf.pojo.User;

/**
 * 只要定义接口方法,所需sql语句在相应UserMapper.xml中映射
 */
public interface UserMapper {

	//一条数据可以返回表对象,属性对应列名
	User find(Integer id);
	//一条数据还可以返回Map,key对应列名
	Map findMap(Integer id);
	//多条数据返回List集合
	List<User> findAll();
	//最多接受一个参数,所以多个参数可以封装成对象传参,
	List<User> findWithIf(User user);
	//多个键值对参数也可以用map传参,key对应列名,value对应列值
	List<User> findByNameAndAge(Map<String, Object> map);
	//多个单值参数也可以用List传参,条件中使用IN操作符
	List<User> findWithIn(List<Integer> ids);
	//条件中使用like操作符
	List<User> findWithLike(String name);
}
 

2.6测试代码

package org.phf.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.phf.factory.MybatisFactory;
import org.phf.mapping.UserMapper;
import org.phf.pojo.User;

public class TestUserMapper {
	
	@Test
	public void test()
	{
		SqlSession session = null;
		try {
			//获取SqlSession的对象(需要手动关闭该资源)
			session = MybatisFactory.getSqlSession();
			//获取业务接口,通过接口类型获取由mybatis生成的匿名实例
			UserMapper userMapper = session.getMapper(UserMapper.class);
			//调用接口方法,执行操作且获得数据
			
			System.out.println("<---------find by id----------->");
			User user = userMapper.find(1);
			System.out.println(user);
			
			System.out.println("<---------findMap----------->");
			Map map = userMapper.findMap(2);
			System.out.println(map);
			
			System.out.println("<---------findAll----------->");
			List<User> userList = userMapper.findAll();
			System.out.println(userList);

			System.out.println("<---------findWithIf----------->");
			user = new User();
			user.setName("phf");
			userList = userMapper.findWithIf(user);
			System.out.println(userList);

			System.out.println("<---------findByNameAndAge----------->");
			Map<String, Object> map1 = new HashMap<String, Object>();
			map1.put("age", 10);
			userList = userMapper.findByNameAndAge(map1);
			System.out.println(userList);
			
			System.out.println("<---------findWithIn----------->");
			List<Integer> list = new ArrayList<>();
			list.add(1);
			list.add(5);
			list.add(10);
			userList = userMapper.findWithIn(list);
			System.out.println(userList);
			
			System.out.println("<---------findWithLike----------->");
			String likeName = "ph";
			userList = userMapper.findWithLike(likeName);
			System.out.println(userList);
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			MybatisFactory.close(session);
		}
	}
}


 3.多对一,一对多 关联的处理

3.1数据库建两表

USE mybatis;
CREATE TABLE tb_clazz(
	id INT PRIMARY KEY AUTO_INCREMENT,
	CODE VARCHAR(16)
	);
	
CREATE TABLE tb_student(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(32),
	sex VARCHAR(2),
	age INT ,
	clazz_id INT,
	CONSTRAINT clazz_fk FOREIGN KEY (clazz_id) REFERENCES  tb_clazz(id)
	);

INSERT INTO tb_clazz(CODE) VALUES('12345');
INSERT INTO tb_clazz(CODE) VALUES('11122');

INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('phf1','男',12,1);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('phf2','男',13,1);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('phf3','男',25,1);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('phf4','男',24,2);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('phf5','女',23,1);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('phf6','男',26,2);


3.2 表映射类

package org.phf.pojo;

public class Student {
	private Integer id;
	private String name;
	private String sex;
	private Integer age;
	//多对一
	private Clazz clazz;
	
	
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Clazz getClazz() {
		return clazz;
	}
	public void setClazz(Clazz clazz) {
		this.clazz = clazz;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", sex=" + sex
				+ ", clazz=" + clazz + "]\n";
	}
}

package org.phf.pojo;

import java.util.List;

public class Clazz {
	private Integer id;
	private String code;
	//一对多
	private List<Student> studentList;
	
	public Clazz() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	
	public List<Student> getStudentList() {
		return studentList;
	}
	public void setStudentList(List<Student> studentList) {
		this.studentList = studentList;
	}
	@Override
	public String toString() {
		return "Clazz [id=" + id + ", code=" + code + ", studentList=\n"
				+ studentList + "]";
	}
}


3.3 XXXMapper.xml和XXXMapper.java接口文件

package org.phf.mapping;
import org.phf.pojo.Student;
public interface StudentMapper {
	Student find(Integer id);
}

<!--StudentMapper.xml--->
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
 "mybatis-3-mapper.dtd">
<mapper namespace="org.phf.mapping.StudentMapper">
	<!--开启缓存-->
  <cache />  
   <!--resultMap标签将column属性(数据库表中的列名) 映射到 property属性(Student对象中的字段)-->
  <resultMap id="clazzResult" type="Clazz">
  	<id column="id" property="id"/>
	<result column="code" property="code"/>
  	</resultMap>
  
 <resultMap id="studentResult" type="Student">
  	<id column="id" property="id"/>
	<result column="name" property="name"/>
	<result column="sex" property="sex"/>
	<result column="age" property="age"/>
	<!--<association>标签体现的是多对一关联关系,-->
	<association property="clazz" javaType="Clazz" resultMap="clazzResult"/>
  	</resultMap>
  
  <select id="find" parameterType="Integer" resultMap="studentResult">
  	SELECT * FROM tb_student s,tb_clazz c
	WHERE s.clazz_id=c.id AND s.id = #{id}
  </select>
</mapper>

 
package org.phf.mapping;
import org.phf.pojo.Clazz;
public interface ClazzMapper {
	Clazz find(Integer id);
}

<!---ClazzMapper.xml---->
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
 "mybatis-3-mapper.dtd">
<mapper namespace="org.phf.mapping.ClazzMapper">
	<!--开启缓存-->
  <cache />  

	<resultMap id="clazzResult" type="Clazz">
		<id column="id" property="id"/>
		<result column="code" property="code"/>
		<collection property="studentList" ofType="Student" 
			column="id" select="findStudentById"/>
	</resultMap>

	<resultMap id="studentResult" type="Student">
		<association property="clazz" javaType="Clazz" column="class_id" select="find"/>
	</resultMap>

	<select id="findStudentById" parameterType="Integer" resultMap="studentResult">
		select * from tb_student where clazz_id=#{class_id}
	</select>
	
	<select id="find" parameterType="Integer" resultMap="clazzResult">
		select * from tb_clazz where id=#{id} 
	</select>
</mapper>


3.4 在mybatis-config.xml文件中增加配置

 
	<typeAliases>
		<typeAlias alias="User" type="org.phf.pojo.User" />
		<typeAlias alias="Student" type="org.phf.pojo.Student" />
		<typeAlias alias="Clazz" type="org.phf.pojo.Clazz" />
	</typeAliases>

	<mappers>
		<mapper resource="org/phf/mapping/UserMapper.xml"/>
		<mapper resource="org/phf/mapping/StudentMapper.xml"/>
		<mapper resource="org/phf/mapping/ClazzMapper.xml"/>
	</mappers>


3.5 测试代码增加

	@Test
	public void testMulti()
	{
		SqlSession session = null;
		try {
			session = MybatisFactory.getSqlSession();
			StudentMapper studentMapper = session.getMapper(StudentMapper.class);
			
			System.out.println("<-----testMulti----Student--find by id------------>");
			Student stu = studentMapper.find(1);
			System.out.println(stu);

			ClazzMapper clazzMapper = session.getMapper(ClazzMapper.class);
			System.out.println("<-----testMulti---Clazz--find by id------------>");
			Clazz clazz = clazzMapper.find(1);
			System.out.println(clazz);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			MybatisFactory.close(session);
		}
	}
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值