mybatis知识

一、mybatis概述

1.1、mybatis
      MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
      mybatis就是一个封装来jdbc的持久层框架,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。它和hibernate都属于ORM框架,但是具体的说,hibernate是一个完全的ORM框架,而mybatis是一个不完全的ORM框架。
1.2、JDBC代码

	 //1.加载驱动
    Class.forName("com.mysql.jdbc.Driver");
	// 2.创建连接数据库对象
    Connection conn=DriverManager.getConnection( "jdbc:mysql://localhost:3306/test4?characterEncoding=utf-8","root","root"); 
	// 3.创建操作数据库对象 
	Statement stat=conn.createStatement();
	 // 4.编写sql语句 
    String sql =" select name from user "; 
 	// 5.执行sql语句,返回结果集
    ResultSet rs=stat.executeQuery(sql);
    // 6.操作结果集 
   while(rs.next()) {  
    System.out.println(rs.getString("name")); 
    } 
    // 7.释放资源 
   rs.close(); 
   stat.close();
   conn.close();

JDBC 存在的问题:

  1. 创建连接时存在硬编码
  2. 在执行statement时存在硬编码
  3. 不停的连接关闭数据库,会使数据库性能降低

1.3、mybatis框架核心配置

  1. mybatis配置文件
  2. mybatis通过读取配置文件,构造出SqlSessionFactroy,即会化工厂。
  3. 通过SQLSessionFactroy,可创建SQLSession
  4. SQLSession不能操作数据库的,通过底层的executor执行器接口来操作数据库
  5. executor执行器要处理的SQL信息是封装到一个底层对象mapperStatement中

二、mybatis入门

1、建库建表
2、操作入门
1)操作思路

  1. 创建entity类
  2. 创建配置文件SQLmapconfig.xml
  3. 编写映射文件
  4. 加载映射文件,在SQLmapconfig.xml中进行加载
  5. 编写测试
    思路:
    a)读取配置文件;
    b)通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
    c)通过SqlSessionFactory创建SqlSession。
    d)调用SqlSession的操作数据库方法。
    关闭SqlSession。
    mybatis参考文档

2)创建entity实体和DAO接口

public class Emp {
	 private Integer id; 
	 private String name;
	 private String age; 
	 private String address;
	 private Date birthday;
	 
	 //创建DAO接口
public interface EmpMapper { 
public Emp selectById(Integer id);
 }

3)在pom.xml中加入依赖

<dependencies>
 <dependency>
	  <groupId>junit</groupId> 
	  <artifactId>junit</artifactId> 
	  <version>4.11</version> 
	  <scope>test</scope> 
  </dependency> 
  <!--mysql连接jar-->
   <dependency> 
	   <groupId>mysql</groupId> 
	   <artifactId>mysql-connector-java</artifactId> 	
	   <version>5.1.6</version> 
   </dependency>
    <!--mybatis依赖-->
     <dependency> 
	     <groupId>org.mybatis</groupId> 
	     <artifactId>mybatis</artifactId>
     	 <version>3.4.6</version> 
      </dependency>
      </dependencies>

4)创建sqlmapconfig.xml文件
可参考mybatis配置文件

<?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="ppbb"> 
   <environment id="ppbb">
   <!--以JDBC的方式提交事物 自动提交 --> 
   <transactionManager type="JDBC"></transactionManager>
   <!--POOLED 表示使用连接池-->
      <dataSource type="POOLED">
      <property name="driver" value="com.mysql.jdbc.Driver"></property>
      <property name="url" value="jdbc:mysql://localhost:3306/test4? characterEncoding=utf-8"></property> 
      <property name="username" value="root"></property> <property name="password" value="root"></property> </dataSource>
         </environment> 
         </environments>                  		  		
         </configuration>

5)创建mapper映射文件
可参考mybatis配置文件

<?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"> <!--namespace:命名空间,给这个mapper.xml在项目取个名字 名称和对应接口的全限定名一致 --> 
<mapper namespace="com.mapper.EmpMapper"> 

	  <!--
	  id:这个标签的名称,唯一标示 和对相应接口的方法名一致
	  parameterType:入参的类型
	  resultType:出参类型 返回值类型
	  resultMap:配置返回值 实体类和表中的类型不匹配的时候 
	  --> 
	 <select id="selectById" parameterType="int" resultType="Emp" resultMap="empResultMap" > 
	 select * from emp where id = #{id} 
	 </select> 
	 </mapper>

6)加载映射文件

<mappers>
 <!--加载单个xml--> 
 <mapper resource="mapper/EmpMapper.xml" /> 
 <!--加载整个包下的xml文件 接口和xml文件的路径要一直 --> 
<!--<package name="com.whhp.k9501.mapper.*" />-->
 </mappers> 

7)测试

public class EmpDemo { 
@Test 
public void selectByIdTest() throws IOException {
 //加载sqlMapConfig.xml文件 
  SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); 
 //获取文件输入流
  InputStream inputStream = Resources.getResourceAsStream("mybatis/SqlMapConfig.xml"); //创建sqlSession工厂 
  SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); 
  //生产
  sqlsession SqlSession sqlSession = sqlSessionFactory.openSession();
//创建mapper接口的实例 
  EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); 
//使用接口
  Emp emp = mapper.selectById(18); 
  System.out.println("emp = " + emp);
  //关闭sqlsession
  sqlSession.close();
  }
 }

三、单表的CRUD

参考mybatis的CRUD

四、入参和出参的类型

1、入参的类型

     入参的参数类型
     基本数据类型 String和基本数据类型的用法一致
     案例:删除数据
     Object对象
     添加和修改
     获取对象中的参数方式:#{属性名称} 对象必须是JavaBean

  1. map
    获取数据的方式:#{键}
//参数为map的方法
 List<Emp> selectEmpMap(Map map); 
 <!--参数为map集合--> 
 <select id="selectEmpMap" parameterType="java.util.Map" resultType="Emp">
  select * from emp where age >= #{age} and address = #{address} 
  </select>
   // 参数为map集合
    @Test
     public void selectEmpMapTest(){ 
     SqlSessionFactory sqlSessionFactory = DBUtil.getSqlSessionFactory("mybatis/SqlMapConfig.xml"); 
     SqlSession sqlSession = sqlSessionFactory.openSession(); 
     EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
      //模拟数据
      Map<String,Object> map =new HashMap<>(); 
      map.put("age",18); map.put("address","蜀国"); 
      //调用方法
       List<Emp> empList = mapper.selectEmpMap(map);
        for (Emp emp : empList) {
         System.out.println("emp = " + emp);
        } 
       }
  1. list
    获取方式:foreach去迭代list集合,产生的元素
    元素是引用数据类型时,参数获取方法#{obj.属性名}
    元素是基本数据类型时,参数获取方法#{obj}
//添加多条数据 
int saveEmpList(List<Emp> empList); 
<!--多条添加--> 
<insert id="saveEmpList" parameterType="java.util.List"> 
	insert into 
  emp(name,age,address,birthday)
 	values
  <foreach collection="list" item="emp" separator=","> 
  (#{emp.name},#{emp.age},#{emp.address},#{emp.birthday}) 
  </foreach>
 </insert>
    // 参数为List集合
     @Test
      public void saveEmpListTest(){
       SqlSessionFactory sqlSessionFactory = DBUtil.getSqlSessionFactory("mybatis/SqlMapConfig.xml"); 
       SqlSession sqlSession = sqlSessionFactory.openSession();
       EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); 
        //模拟数据
         List<Emp> empList =new ArrayList<Emp>(); 
         empList.add(new Emp("诸葛亮",23,"襄阳",new Date(2500000))); 
         empList.add(new Emp("诸葛瑾",28,"南京",new Date(60000000000L)));
         empList.add(new Emp("庞统",35,"成都",new Date(5246843218L)));
         empList.add(new Emp("周瑜",18,"南京",new Date(250000)));
            //调用方法 
            int i = mapper.saveEmpList(empList); 
            sqlSession.commit();
            System.out.println("i = " + i);
   }
  1. 数组
    获取方式:foreach去迭代数组,产生的元素
    参数获取方式:#{item}
//删除多条多条数据 
int deleteEmpAraay(int[] ids);
 <!--deleteEmpAraay删除多条-->
  <delete id="deleteEmpAraay" > 
    delete from emp where id 
  	in
   <foreach
    collection="array" item="id" open="(" close=")" separator=","> 
    #{id} 
  </foreach>
 </delete>
 // 多条删除
  @Test
   public void deleteEmpArrayTest(){ 
   SqlSessionFactory sqlSessionFactory = DBUtil.getSqlSessionFactory("mybatis/SqlMapConfig.xml"); 
   SqlSession sqlSession = sqlSessionFactory.openSession();
    EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
     //模拟数据 
     int[] ids ={45,47,50,3};
      //调用方法
       int i = mapper.deleteEmpAraay(ids); 
       sqlSession.commit(); 
       System.out.println("i = " + i);
 }

2、出参的类型
resultType,resultMap 返回值的类型 Emp
返回值是单条数据
emp
返回值是多条数据
List
区别:
如果实体类属性和表中的字段 无法直接匹配时我们就使用resultMap处理属性

<!--配置返回值类型--> 
    <!--实体类型--> 
<resultMap id="bookResultMap" type="Book">
    <!--与表中主键相对应的属性配置--> 
 <id property="bookId" column="book_id"></id> 
    <!--其他对相应的属性-->
 <result property="bookName" column="book_name"></result> 
 <result property="bookAuthor" column="book_author">
 </result> <result property="bookSaleTime" column="book_saleTime" javaType="java.sql.Date"></result>
 <result property="bookPrice" column="book_price"> </result> 
 <result property="bookType" column="book_type"></result> 
 </resultMap>
    <!--查询全部--> 
 <select id="selectBookAll" resultMap="bookResultMap">
     select * from book 
 </select>

3、分页查询
需要两个参数
起始数,每页条数
使用map集合作为参数

//分页查询
 List<Book> selectBookAllFY(Map map);
  <!--分页--> 
  <select id="selectBookAllFY" parameterType="java.util.Map" resultMap="bookResultMap"> 
  select * from book limit #{start} , #{size} 
  </select> 
  //分页测试 
  @Test
   public void selectEmpAllFYTest() throws IOException { //获取配置文件输入流
    SqlSessionFactory sqlSessionFactory = DBUtil.getSqlSessionFactory("mybatis/SqlMapConfig.xml"); 
    SqlSession sqlSession = sqlSessionFactory.openSession();
     //获取BookMapper的实现类对象 
     BookMapper bookMapper = sqlSession.getMapper(BookMapper.class);
      //模拟参数
       Map map = new HashMap<String,Object>(); 
       map.put("start",0); map.put("size",5); 
       //调用分页查询
        List<Book> bookList = bookMapper.selectBookAllFY(map);
         for (Book book : bookList) { 
         System.out.println("book = " + book);
      }
 }

4、条件查询

//条件查询
 List<Book> selectBookAllTJ(Map map); 
 <!--条件查询 书名,价格范文 --> 
 <select id="selectBookAllTJ" parameterType="java.util.Map" resultMap="bookResultMap"> 
 select * from book where 1=1 
 <if test="name != null"> and book_name like '%${name}%' </if> 
 <if test="priceFrom!=null"> and book_price &gt;= #{priceFrom} </if> 
 <if test="priceTo !=null"> and book_price &lt;= #{priceTo} </if>
  </select> 
  
  // 条件查询 
  @Test 
  public void selectEmpAllTJ(){
   //获取配置文件输入流
   SqlSessionFactory sqlSessionFactory = DBUtil.getSqlSessionFactory("mybatis/SqlMapConfig.xml"); SqlSession sqlSession = sqlSessionFactory.openSession(); 
   //获取BookMapper的实现类对象
    BookMapper bookMapper = sqlSession.getMapper(BookMapper.class);
     //模拟数据 
     Map map = new HashMap<String,Object>(); 
     map.put("name","鹿"); map.put("priceFrom",100); 
     map.put("priceTo",200); List<Book> bookList = bookMapper.selectBookAllTJ(map);
      for (Book book : bookList) { 
      System.out.println("book = " + book);
       } 
  }

小结:
parameterType和resultType
parameterType指定输入参数的java类型,可以填写别名或Java类的全限定名。
resultType指定输出结果的java类型,可以填写别名或Java类的全限定名。

#{}和${}
#{}:相当于预处理中的占位符?。
#{}里面的参数表示接收java输入参数的名称。
#{}可以接受HashMap、POJO类型的参数。
当接受简单类型的参数时,#{}里面可以是value,也可以是其它。
#{}可以防止SQL注入。
${}:相当于拼接SQL串,对传入的值不做任何解释的原样输出。
${}会引起SQL注入,所以要谨慎使用。
${}可以接受HashMap、POJO类型的参数。

当接受简单类型的参数时,${}里面只能是value。

selectOne和selectList
selectOne:只能查询0或1条记录,大于1条记录的话,会报错:
selectList:可以查询0或N条记录

五、多表查询

1.案例:用户和订单
在这里插入图片描述
      user和orders:
User 与orders:一个用户可以创建多个订单,一对多
Orders 与 user:多个订单只由一个用户创建,多对一
      orders和orderdetail:
Orders 与 orderdetail:一个订单可以包括 多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在orderdetail记录,一对多关系
orderdetail 与orders:多个订单明细包括在一个订单中, 多对一
      orderdetail和items:
Orderdetail 与 items:多个订单明细只对应一个商品信息,多对一
Items 与 orderdetail:一个商品可以包括在多个订单明细 ,一对多
需求:
根据商品ID查找订单信息,包括用户名和地址

#查找id为6的所有定单
SELECT 
	orders.id, orders.number,orders.createtime,orders.note,`user`.username,`user`.address
FROM 
	orders ,`user` 
WHERE 
	orders.user_id = `user`.id AND `user`.id = 6;
  1. 一对一
    1)一对一resultType实现
    复杂查询时,单表对应的实体类已不能满足输出结果集的映射。所以要根据需求建立一个扩展类来作为resultType的类型。
    1.1、创建一个订单的扩展类
public class OrdersExt extends Orders{
	private String username;
	private String address;
	//set和get略
}

1.2、声明一接口

public interface OrdersMapper{
	public OrdersExt findOrdersUser(int ordersId);
}

1.3、编写配置文件

<?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"> <!--namespace:命名空间,给这个mapper.xml在项目取个名字 名称和对应接口的全限定名一致 --> 
<mapper namespace="com.mapper.OrdersMapper"> 
	<sql id="select_orders">
	orders.id,
	orders.number,
	orders.createtime,
	orders.note,
	</sql>
	
	<sql id="select_user">
	user.username,
	user,address
	</sql>
	
	<select id="findOrdersUser" parameterType="int" resultType="ordersExt">
	select 
	<include refid="select_ordrs"/>
	<include refid="select_user"/>
	from
	ordrs o,user s
	where
	o.id=s.id 
	and
	o.id=#{?};
	</select>
</mapper>

1.4、加载映射文件

<mappers>
	<mapper resource="com/mapper/OrdresMapper.xml"/>
</mappers>

1.5、测试

//测试
@test
public void test1 throws Exception {
	SqlSession session = ssf.openSession();
	//通过session获取代理
	OrdresMapper ordresMapper = session.getMapper(OrdresMapper.class);
	OrdersExt ordersExt =  ordersMapper.findOrdersUser(3);
	Sysout.out.prinln(ordersExt );
	session.close;
}

2)一对一resultMap实现

掌握association的使用

2.1、编写接口

public Orders findOrdersBylMap(int ordersId);

2.2、编写配置文件

<resultMap type="orders" id="ordersResulMap">
	<result colum="id" property="id"/>
	<result colum="number" property="number"/>
	<result colum="createtime" property="createtime"/>
	<result colum="note" property="note"/>
	
	<!--关联内部对象-->
	
	<association property="user" javaType="com.entity.User">
	<result colum="username" property="username"/>
	<result colum="address" property="address"/>
	</association>
</resultMap>
<select id="findOrdersBylMap" parameterType="int" resultMap="ordersResulMap">
	select 
		<include refid="select_ordrs"/>
		<include refid="select_user"/>
	from
		ordrs o,user s
	where
		o.id=s.id 
	and
		o.id=#{?};
</select>

2.3、测试

//测试
@test
public void test2 throws Exception {
	SqlSession session = ssf.openSession();
	//通过session获取代理
	OrdresMapper ordresMapper = session.getMapper(OrdresMapper.class);
	Orders orders =  ordersMapper.findOrdersBylMap(5);
	Sysout.out.prinln(orders );
	session.close;

小结:
resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType。

resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的对象属性中。

resultMap可以实现延迟加载,resultType无法实现延迟加载。
4. 一对多
需求:
根据定单ID查找定单信息、用户信息和定单明细信息
4.1、在orders中添加定单信息

//用户信息
private User user;
//订单信息
private List<Orderdetail> orderdetails;

4.2、编写接口

public Orders findOrdersByRslMap(int ordersId);

4.3、编写xml配置文件

<resultMap type="orders" id="ordersResulMap">
	<result colum="id" property="id"/>
	<result colum="number" property="number"/>
	<result colum="createtime" property="createtime"/>
	<result colum="note" property="note"/>
	
	<!--关联内部对象-->
	
	<association property="user" javaType="com.entity.User">
	<result colum="username" property="username"/>
	<result colum="address" property="address"/>
	</association>
	
	<!--一对多对应的集合-->
	
	<collection property="orderdetails" ofType="orderdetail">
	<id colum="datail_id" property="id"/>
	<result colum="items_id" property="itemsId"/>
	<result colum="items_num" property="itemsNum"/>
	</collection>
</resultMap>
<select id="findOrdersByRslMap" parameterType="int" resultMap="ordersResulMap">
	select 
		orders.id,
		orders.user_id,
		orders.createtime,
		orders.note,
		user.username,
		user.adderss,
		orderdetail.id detail_id,
		orderdetail.itemd_id,
		orderdetail.itemd_num
	from
		orders o,user u,orderdetail d
	where
		o.user_id=u.id 
	and
		o.id=d.orders_id
	and
		o.id=#{?}	;
</select>

4.4、测试

//测试
@test
public void test2 throws Exception {
	SqlSession session = ssf.openSession();
	//通过session获取代理
	OrdresMapper ordresMapper = session.getMapper(OrdresMapper.class);
	Orders orders =  ordersMapper.findOrdersByRslMap(7);
	Sysout.out.prinln(orders );
	session.close;
  1. 多对多
    需求
    查询用户信息及用户购买的商品信息,要求将关联信息映射到主pojo的pojo属性中
    6.1、User/Orders/Orderdetail.java
//在user实体中加入订单列表
private List<Orders> ordersList;
//在orsers实体中加入订单明细
private List<Orderdetail> orderdetailList;
//在Orderdetail实体中加入商品信息
priv Items items;

6.2、编写接口

public Lise<User> findUserAndItemRslMap();

6.3、编写mapper.xml文件

<mapper namespace="com.mapper.UserMapper">
	<resultMap id="userAndItemRslMap" type="user"> 
		<id column="id" property="id"/>
		<result columu="username" property="username"/>
		<result columu="address" property="address"/>
		
	<!--collection中嵌套collection 嵌套association -->
	<!--1.user的ordersList属性-->
	
	<collection property="ordersList" ofType="orders">
		<id column="orders_id" property="id"/>
		<result columu="numder" property="numder"/>
		<result columu="createtime" property="createtime"/>
		<result columu="note" property="note"/>
		
		<!--2.orders的orderdetails属性-->
	
		
	    <collection property="orderdetails" ofType="orderdetails">
		<id column="details_id" property="id"/>
		<result columu="items_id" property="itemsId"/>
		<result columu="items_num" property="itemsNum"/>
		
		 <!--3.orderdetails的items的属性-->

		 
		<association property="items" javaType="com.Items">
	    <id column="items_id" property="id"/>
		<result columu="items_name" property="name"/>
		<result columu="items_detail" property="detail"/>
		 </association>
		</cillection>
	</collection >
	</resultMap>
	<select id="findUserAndItemRslMap" resultMap="userAndItemRslMap">
	select
		user.id,
		user.username,
		user,adderss,
		orders.id orders_id,
		orders.user_id,
		orders.number,
		orders.createtime,
		orders.note,
		orderdetail.id detail_id,
		orderdetail.items_id,
		orderdetail.items_num,
		items.name items_name,
		items.detail items_detail
	from
		user,orders,orderdetail,items
	where
		user.id=oedres.user_id
	and
		orders.id=orderdetail.orders_id
	and
		orderdetail.items_id=items.id				
	</select>
</mapper>

6.4、测试

@test
	public void test4() throws Exception{
	SqlSession session = ssf.openSession();
	UserMapper userMapper=session.getMapper(UserMapper.class);
	List<User> userList=userMapper.findUserAndItemRslMap();
	System.out.println(userList.size());
	for(User user:userList){
	System.out.println("用户名:"+user.getUsername()+"-地址"+user.getAddress());
		for(Orders orders:getOrdersList()){
			System.out.println("定单Id:"+orders.getId());
			System.out.println("定单Number:"+orders.getNumber());
			System.out.println("定单时间:"+orders.getCreatetiem);
			for(Orderdetail detail:order.getOrderdetails()){
			System.out.println();
			System.out.print("商品数量:"+detail.getItemsNum());
			System.out.print("商品名称:"+detail.getItems().getName);
			System.out.print("商品详情:"+detail.getItems().getDetail());
			}
			System.out.println();
			System.out.println("-------------------------");
		}
	}
	session.close;
}

于有错误请指点!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值