Mybatis

Mybatis

1.为什么使用mybatis

MyBatis是一个半自动化的持久化层框架。

JDBC
SQL夹在Java代码块里,耦合度高导致硬编码内伤
维护不易且实际开发需求中sql是有变化,频繁修改的情况多见

Hibernate和JPA
长难复杂SQL,对于Hibernate而言处理也不容易
内部自动生产的SQL,不容易做特殊优化
基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难,导致数据库性能下降

对开发人员而言,核心sql还是需要自己优化

sql和java编码分开,功能边界清晰,一个专注业务、一个专注数据

2.下载地址

3.HelloWorld

<!-- sql demo-->
CREATE TABLE `employee` (
  `id` varchar(50) NOT NULL default '',
  `name` varchar(50) default NULL,
  `gender` char(1) default NULL,
  `address` varchar(100) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `employee` VALUES ('1', '张全蛋', '1', '暴走大事件');
INSERT INTO `employee` VALUES ('2', '王尼玛', '1', '暴走大事件');
INSERT INTO `employee` VALUES ('3', '李小华', '0', '富士康');
INSERT INTO `employee` VALUES ('4', '赵铁柱', '1', '富士康');
INSERT INTO `employee` VALUES ('5', '风清扬', '1', '华山');
INSERT INTO `employee` VALUES ('6', '周杰伦', '1', '台北');
INSERT INTO `employee` VALUES ('7', '卡死了', '1', '我说的');

使用步骤:

  1. 导入jar包

2)添加mybatis全局配置文件,log4j日志文件,数据源信息文件

3)创建实例类(POJO,domain,javaBean,entity),实体类的映射文件(sql映射文件)

4)将映射文件注册到mybatis全局配置文件中

5)编写SQL,根据全局配置文件拿到SqlSessionFactory,通过SqlSessionFactory拿到SqlSession对象,调用封装好的方法进行CRUD,关闭会话。

package com.igeek.pojo;

public class Employee {

	private String id ;
	private String name;
	private char gender;
	private String address;
	
}

<?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">
<!-- 每一个实体类 都对应着Mybatis的一个命名空间 。   namespace属性值 相当于id,如果存在多个 不允许重复-->
<!-- 命名空间,一般情况下,在当前空间中声明的是,实体类对应的别名 -->
<mapper namespace="hello">
	<select id="selOne" resultType="com.igeek.pojo.Employee">
		select * from employee where id=#{id} 
	</select>
	<!-- resultMap:表示结果集,注意:单一的一个resultMap表示一个实体类对象
	id:表示当前resultMap的名称,type表示当前结果集的类型,可以使用别名,也可以使用类地址
	注意:查询列表时,会将所有的单一实体类封装到list容器中 -->
    <!-- 创建半自动sql -->
    <!-- select标签,表示查询操作,id:表示标签名称,resultMap:表示查询到的结果类型 -->
    <!--  注意:resultMap表示当前SQL语句查询到的结果   类型跟前面resultMap 标签中的id属性值 相对应。 -->
      <!-- 按条件查询   id 表示标识当前查询标签的,能够通过id来执行指定的SQL语句。 parameterType表示传递过来参数类型。 -->
      <!-- #{s_id}  #{ } 表示占位符 。  s_id 随便写 ,在mybatis中 最好写的跟字段一致 。-->
</mapper>
try {
		//根据全局配置文件。利用SqlSessionFactoryBuilder创建数据库会话工厂对象。
		Reader reader = Resources.getResourceAsReader("resource.xml");
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		//通过会话工厂获取SqlSession对象,一个SqlSession对象代表和数据库的一次会话
		SqlSession session = sqlSessionFactory.openSession();
		//推荐使用namespace+id,防止多个配置文件中的id重复。
		Employee emp = session.selectOne("hello.selOne", "1");	
		System.out.println(emp);
		//每次使用完需要关闭sqlsession对象。(必须)
		session.close();
		//注意:SqlSession跟connection一样都不是线程安全的,因此不能被共享。不推荐写成成员变量。每次使用重新获取。
} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
} 

##4.mybatis三种开发模式

1.请看上面HelloWorld的demo

​ (存在问题,每次都要指定查询那个命名空间下的那个标签的sql,类型是object类型)

2.使用接口+配置文件

​ (接口与配置文件动态绑定。mybatis会为接口自动创建代理对象)

​ (注意:1.需要将namespace中的值,写成接口的全路径 2.接口方法名称跟标签id一致)

​ (使用接口式优点,有明确的返回值,更严格的类型检查。将规范与实现分离,可以使用不同的持久层技术,方便开发扩展以及维护。)

3.使用接口+注解

SqlSession可以直接调用方法的id进行数据库操作,但是我们一般还是推荐使用SqlSession获取到Dao接口的代理类,执行代理对象的方法,可以更安全的进行类型检查操作。。。 推荐使用第二种开发模式!!!!!

//第二种方式的demo...
	@Test
	public void test2(){
		SqlSession session = getSqlSession();
		EmployeeDao employeeDao = session.getMapper(EmployeeDao.class);
		System.out.println(employeeDao.getClass());
		Employee employee = employeeDao.selOne(2);
		System.out.println(employee);
	}
	
	//封装一个获取sqlsession对象的方法。
	public SqlSession getSqlSession(){
		Reader reader=null;
		try {
			reader = Resources.getResourceAsReader("resource.xml");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		//通过会话工厂获取SqlSession对象,一个SqlSession对象代表和数据库的一次会话
		SqlSession session = sqlSessionFactory.openSession();
		return session;
	}

##5.全局配属属性内容

settings

typeAliases

typeHandlers

typeHandlers JDK1.8 日期类 JSR310规范,时间类型处理器。

plugins

环境中的自定义数据源,默认使用mybatis提供的数据源

数据库厂商支持(全局文件中配置完,在映射文件中配置当前SQL在那个数据库环境下执行.)

mapper注册一个SQL映射

6.DTD设置

7.Mapper中的CRUD

<!-- parameterType可以省略。 -->
  	 <insert id="insertEmp" parameterType="com.igeek.pojo.Employee">
  		insert into employee values(#{id},#{name},#{gender},#{address})
  	</insert>
    <update id="updateEmp">
    	update employee set name = #{name},gender = #{gender},address=#{address}
    	where id = #{id}
    </update>
    <delete id="deleteEmp">
    	delete from employee where id = #{id}
    </delete> 
	@Test
	public void test2(){
		SqlSession session = getSqlSession();
		EmployeeDao employeeDao = session.getMapper(EmployeeDao.class);
		Employee employee = new Employee();
		employee.setId("7");
		employeeDao.deleteEmp(employee);
		//注意,拿到的sqlSession对象需要手动的提交,接口中的返回值类型可以是void,int long boolean
        //可以设置自动提交工厂对象.openSession(true);
		session.commit();
		session.close();
	}	

8.mybatis使用主键自增

<!-- 
useGeneratedKeys="true" keyProperty="id" 

Oracle不支持主键自增,使用序列。
select * from user_sequences;查询用户下所有表的序列名称。
select 序列名称.nextval from dual;
-->

9.#{}中的参数处理

1.当传递的参数只有一个的时候,mybatis不会做特殊处理。

2.当传递多个参数的时候,mybatis会封装一个Map,当前map的key 默认是param1...paramN,取的时候使用key拿到value,也可以通过索引。可以在接口方法中使用@Param注解来直接封装map的key...如果多个参数的话推荐传入POJO,通过#{属性名}来取出。也可以直接在接口声明位置传入一个map集合。如果经常使用可以创建一个TO对象,封装数据信息。(transfer object)

public Employee getEmp(@Param("id")Integer id,String lastName);
	取值:id==>#{id/param1}   lastName==>#{param2}

public Employee getEmp(Integer id,@Param("e")Employee emp);
	取值:id==>#{param1}    lastName===>#{param2.lastName/e.lastName}

##特别注意:如果是Collection(List、Set)类型或者是数组,
		 也会特殊处理。也是把传入的list或者数组封装在map中。
			key:Collection(collection),如果是List还可以使用这个key(list)
				数组(array)
public Employee getEmpById(List<Integer> ids);
	取值:取出第一个id的值:   #{list[0]}

10.#{}与${}区别

#{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
${}:取出的值直接拼装在sql语句中;会有安全问题;
大多情况下,我们去参数的值都应该去使用#{};
sql语句中不支持占位符 ( ? ) 的地方需要使用${}取值  比如orderby 排序。

11.集合数据的查询

方法的返回值类型为List嵌套实体类,select标签中resultType指定集合中对象的类型即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值