Mybatis详解(一)

资源文件可以下载,在我个人的资源文件里(MyBatis1.rar)

mybatis简介
mybatis框架执行原理
mybatis初次的入门案例
mybatis配置文件详解
mybatis 方法多参数的处理
mybatis返回主键值
sql代码段
自定义结果类型ResultMap

(一)Mybatis简介
mybatis本身是一个轻量级的持久化层框架(1.何为持久化。2.何为序列化操作),本身也是基于JDBC的封装(JDBC的链接步骤).开发者本身更多的关注SQL语句的执行效率,除此之外mybatis也是一个半自动的ORM映射框架(支持一对一,一对多的实现,多对多采用两个一对多进行实现)
注意:实际的开发过程中,因为大量的关系相互映射的存在,在查询数据这一块不便于后期项目本身的项目维护扩展。所以更多的方向是思考数据库中的设计和利用本身mybatis提供的数据自定义封装和其它的类似缓存机制的特点,解决开发中的数据设计结构

mybatis优势:
1、比起jdbc减少了一些重复的代码量操作,也方便能够集成到后期的管理框架中
2、mybatis提供在xml中编写sql语句,不直接将sql语句入侵到代码中
3、分别提供的xml标签和mapper标签(xml标签可实现动态SQL语句,也就是嵌入条件判断和循环,比较类似存储函数),mapper标签支持对象正确的解析至数据库中

mybatis框架执行原理
sqlConfigXMl配置文件(一个全局的配置文件)(可配置映射文件和连接数据源和事务等)
在这里插入图片描述
在这里插入图片描述
通过配置文件构建出可构建操作数据会话的会话工厂,也就是我们常说的sqlSessionFactory(涉及工厂模式代码设计)
通过sqlSessionFactory生产出相互独立的sqlsession,为什么是独立的会话,既然是独立的会话,那也有全局的会话(简单提及缓存)进行数据库层面上面的操作
sqlsession之所以能够操作,依赖一个叫Executor的执行器,通过该执行器进行数据库的CRUD操作

Executor的执行器需要操作CRUD的动作由谁而来,就是由mapperstatement对象读取mapper映射文件
在这里插入图片描述
mybatis入门搭建步骤
1.在src目录下配置一个log4j.properties(可选)方便我们监听到mybatis进行的动作(sql执行过程)

\# set level
log4j.rootLogger=DEBUG, stdout

\# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

2、构建一个简单的web项目,在lib目录下导入如下的jar包
在这里插入图片描述
在这里插入图片描述
3、src目录下构建mybatis的全局配置文件mybatisCfg.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>
	<!-- 数据库连接环境配置 -->
	<environments default="development">
		<!-- 标明mybaitis环境 id唯一 -->
		<environment id="development">
			<!-- JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。 它依赖于从数据源得 到的连接来管理事务范围。JDBC默认是自动提交 -->
			<transactionManager type="JDBC" />
			<!-- 采用数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<!-- 避免环境的不统一,造成数据操作乱码 -->
				<property name="url"
				<!-- 分别是://数据库地址:数据库端口号/数据库名称?字符集设置 -->
					value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
					<!-- 数据库连接用户名及密码 -->
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	<!-- 添加需要被映射的文件(即编写Mapper映射文件) -->
	<mappers>
		<mapper resource="com/wwj/dao/PersonMapper.xml" />
	</mappers>
</configuration>

构建模型类 com.wwj.model 和 数据库表

import java.io.Serializable;
import java.util.Date;
/**
 * 基本的模型类
 * @author wwj
 *对象序列化是一个用于将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或通过网络发送到任何其他程序;从字节流创建对象的相反的过程称为反序列化。而创建的字节流是与平台无关的,在一个平台上序列化的对象可以在不同的平台上反序列化。
 *无需序列化的变量使用transient
 */
public class Person implements Serializable {
	//Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的
	//这里是用来表明版本的一致性
	private static final long serialVersionUID = 2680875170108959939L;
	
	private  Integer   id;
	private  String name;
	private  Date bir;
	private  String address;
	//自行get和set
	}

构建数据库表
在这里插入图片描述
创建数据层的操作也就是mapper的操作接口

/**
 * person层的操作
 * 
 * @author Yun
 *
 */
public interface PersonDao {
	/**
	 * 新增用户
	 * 
	 * @param p
	 *            传入需要新增的对象
	 * @return 0,1代表结果
	 */
	int savePerson(Person p);

	/**
	 * 更新用户对象
	 * @param p 需要被更新的对象
	 * @return 0,1代表结果
	 */
	int updatePerson(Person p);

	/**
	 * 根据用户id进行删除
	 * @param id  唯一用户id
	 * @return  0,1代表结果
	 */
	int  deletePersonById(int  id);
	
	/**
	 * 获取所有的信息
	 * @return  所有的人员信息
	 */
	List<Person>  getPersonInfos();
}

构建对应的mapper映射文件命名为PersonMapper.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接口的全路径名称 -->
<mapper namespace="com.wwj.dao.PersonDao">
	<insert id="savePerson" parameterType="com.wwj.model.Person">
		insert into
		person(name,address,bir) values(#{name},#{address},#{bir});
	</insert>

	<update id="updatePerson" parameterType="com.wwj.model.Person">
		update person set
		name=#{p.name},address=#{address},bir=#{bir}
		where id=#{id}
	</update>

	<delete id="deletePersonById" parameterType="int">
		delete from person
		where id=#{id}
	</delete>


	<select id="getPersonInfos" resultType="com.wwj.model.Person">
		select * from person
	</select>

</mapper>

编写完Mapper后一点要将映射加入到全局配置mybatisCfg.xml,文件中,否者不会生效
在这里插入图片描述
编码测试

/**
 * 测试mybatis的CRUD操作
 * 
 * @author wwj
 *
 */
public class TestMybatis {
	public static void main(String[] args) throws IOException, ParseException {
		/*
		 * 日期上面的处理
		 */
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
		String format = sf.format(new Date());
		Date parse = sf.parse(format);

		InputStream is = Resources.getResourceAsStream("mybatisCfg.xml");
		SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
		// 生成 session
		SqlSession session = build.openSession();
		Person per = new Person();
		per.setName(" 小王 ");
		per.setAddress(" 重庆 ");
		per.setBir(parse);
		// 操作数据
		int insert = session.insert("savePerson",per);
		// 提交事务
		session.commit();
		// 关闭 session
		session.close();
		
	}
}

(三)Mybatis配置文件详解
全局配置文件mybatisCfg.xml详解:
environments环境配置,可以配置多种环境 default指定使用某种环境.
transactionManager事务管理器有两种取值JDBC,managed.我们选择jdbc即可
dataSource配置数据源,采用默认的连接池选择项POOLED
mappers里面填入需要进行数据操作xml标签用于执行的动作
映射的数据操作文件需要和接口保持同个路径(可以把mapper当成接口的实现类)

映射文件PersonMapper.xml详解
namespace表明需要对应动作的空间即是接口所在的全路径名称
id与接口中的方法保持一致
parameterType填写自定义对象的全路径名称
接收参数采用 #{objAttrName}

(四)Mybatis方法多参数接收(代码示例)
1、索引接收(了解即可)

//在接口中
List<Person>  getPersonInfosByNameAndID(String name ,int id);
//在影射文件中
<select id="getPersonInfosByNameAndID" >
  		select * from person where name = #{0} and id = #{1} 
  	</select>

2、map接收(重点)

//在接口中
 /**
     *  根据map进行查询
     * @param attrs
     * key1 id  key2 name
     * @return
     */
    List<Person>  getPersonInfosByMap(Map attrs);
//在影射文件中
<select id="getPersonInfosByMap"  parameterType="java.util.Map" resultType="com.wwj.model.Person">
		select * from person where id =
		#{id} and name = #{name}
	</select>
	//----------------调用测试类中
	  Map<String,Object>  attrs = new HashMap<>();
		attrs.put("id", 2);
		attrs.put("name", "小王");
		session.selectList("getPersonInfosByMap", attrs);

3、.注解@Param接收(重点)

/**
     * 根据用户唯一id查询信息
     * @param id
     * @return
     */
    Person  getPersonInfo(@Param("pid") int id);
    //---------------动作实现
	<select id="getPersonInfo" 
		resultType="com.wwj.model.Person">
		select * from person where id =#{pid}
	</select>
	//---------调用测试
	session.selectOne("getPersonInfo", 2);

(五)Mybatis立即返回主键
应用场景:当我们需要在当前事务插入数据后立即获取数据的主键id,做下一步额外操作,并且不因为并发高的情况下取错值而考虑

 <insert id="savePerson" parameterType="com.wwj.model.Person">
		<selectKey keyProperty="id" resultType="int" order="AFTER">
			select last_insert_id()
		</selectKey>
		insert into
		person(name,address,bir) values(#{name},#{address},#{bir});
	</insert>
	//------------------------------------------------------------
		// 操作数据
		Person p = new Person();
		p.setName("小小王");
		p.setBir(parse);
		int result = session.insert("savePerson", p);
		System.out.println(result);
		//原本我们的p对象是没有主键id的,主键id是数据库表中id项自增长自动生成的,
		//当我们设置了立即返回主键后,在我们插入一个对象时,我们就可以立即获取并返回数据库生成的那个id。所以下面可以打印出id
		System.out.println(p.getId());

keyProperty=”返回主键的id的属性名”
resultType=”主键类型”
order=”“什么时候执行,在SQL执行前还是执行后执行,两个取值:BEFORE和AFTER
select last_insert_id()取到最后生成的主键,只在当前事务中取

sql代码段
如果场景中有大量的重复的公共sql语句,那么可以考虑使用声明公共的部分
示例如下:

/**
     * sql片段
     * @param id  根据用户的id查询姓名
     * @return
     */
  String  getPersonName(@Param("pid") int id);
    //--------动作实现
  <sql id="nameCol"> name</sql>
	<select id="getPersonName"   resultType="java.lang.String">
		select 
		<!--在这里引入公共的sql代码段-->
		<include refid="nameCol"></include>
		from person where
		id =
		#{pid}
	</select>
	//--------测试调用
		String name  = session.selectOne("getPersonName",2);
		System.out.println(name);

自定义结果类型ResultMap(开发中长期使用)
应用场景:假设我们的实际开发过程中,数据表组合字段多,又不想关心配置映射关系,只想关心sql语句,以及结果,并且也关心sql语句的效率

假设2张表 person和card 1:m关系
连接查询需要person中的人名和card表中的卡号名字

//----- 实体类
public class Card {
		private String cname;
		}
public class Person implements Serializable {
	private  Integer   id;
	private  String name;
	private  Date bir;
	private  String address;
	private  List<Card>  cards;
	}
//----构建自定义的resultmap封装 注意   collection(集合)association(联系)
	<resultMap type="com.wwj.model.Person" id="personRS">
		<!--column指向数据库列名 property指向pojo对象中字段名 -->
		<result column="name" property="name" />
		<!-- property指的是在bean中字段名 ofType类的全定向名 -->
		<collection property="cards" ofType="com.wwj.model.Card">
			<result column="cname" property="cname" />
		</collection>
	</resultMap>
//--------映射的动作实现
    <select id="getPersonsOfCard" resultMap="personRS">
        select
        person.name,card.cname
        from person
        INNER JOIN card
        on person.id = card.pid
    </select>
//--------代码操作
		List<Person> persons = session.selectList("getPersonsOfCard");
		for (Person person : persons) {
			System.out.println(person.getCards().get(0).getCname());
			System.out.println(person.getCards().get(1).getCname());
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值