myBatis入门学习_下
2018-01-07 22:41
295 查看
myBatis入门学习_下:
本章主要讲动态sql,关联查询,spring整合,,如果是初次学习myBatis的同学,请先阅读myBatis入门学习_上
话不多说,上来就是一个需求,惊不惊喜,意不意外 嘿嘿
- 需要数据的小伙伴请点击myBatis入门学习_上,获取数据库数据…
- 然后粗略的介绍一下Vo,其实就是valueObject的简写,因为select 参数类型只能有一个,我们就是用vo来做数据的存储的…
好了..我们创建一个queryVo
然后在配置文件里写sql语句…
这里使用的是mapper接口方式写代码,就不写实体类了,
userMapper 接口新增方法
编写测试代码
查询结果如下,
其实动态if啥的没啥好讲的,,看几个案例就懂了,
有7种可能性,如果不使用动态if,那么我们就得写七条sql,,那不是得累死……
有的小伙伴估计要怼我了,,明明就是六种,你硬要说成七种,你是不是傻,,,还有一种可能是就3个值都是null,那就是查询所有
开始写代码把…………先写sql
那个,,, if 有什么作用就不用我来讲了把…….如果真不懂,,那我也没辙了….
接口新增方法…
测试代码
运行结果是没问题的,
这时可能就有同学不耐烦了,写sql还要加上 where 1 = 1 ,那么麻烦,不学了
4000
别急,myBatis 给我们提供了标签,加上了就不用写了,不信的话我去试试
然后我这次再加个条件测试一波
哎呀,,出问题了,,,,但是好像不是标签的问题,去瞄一下sql语句,
其实使用 #{} 是不能使用引号的,,
然后去掉引号,再测试,
我们先在脑子意淫一下sql 语句
select * from 订单 where 订单.用户id in(a,b,c);
有小伙伴肯定跟我开始想一块了, 把 list遍历一下,然后拼接成字符串 a,b,c 然后把 a,b,c 当成一个参数传过去 /坏笑,这种事想想就好了啊 ahhh
我们在Vo对象里写一个List属性,传的话就传一个Vo过去,,
然后我们来编写sql
嘿嘿,看傻了把, 我来解释一下把
collection=”users”的意思是 遍历 cn.mybatis.pojo.QueryVo 对象里的 users属性,
open=”(” 循环开始符号,
close=”)” 循环结束符号,
item=”uid” 循环的值
separator=”,” 分割符
假如只循环二次 , 一开始产生一个”and id in (“符号,此时 sql语句是这样的
select * from orders o,user u where 1 = 1 and u.id in (
然后拿到值 uid 拼接到sql中去后,sql 语句是这样的
select * from orders o,user u where 1 = 1 and u.id in ( a
然后结束第一次循环,开始第二次,然后sql语句是这样的
select * from orders o,user u where 1 = 1 and u.id in ( a ,
然后又拿到值
select * from orders o,user u where 1 = 1 and u.id in ( a ,b
最后,循环完毕,sql 语句是这样的
select * from orders o,user u where 1 = 1 and id u.in ( a ,b)
接口添加方法
我们写测试代码测试一下
看看生成的sql语句
代码测试
讲的东西有点杂,,,需要好好理一下才行,,最开始我是一脸懵的,,
案例需求(一对一查询)
查询所有订单信息,关联查询下单用户信息。
需要注意的是,因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单
订单表如下
这里提供俩种方案,
设置返回结果为po类
使用resultMap
编写sql
接口增加方法
编写测试类
为了更好的展示运行结果,,我使用debug来截图
创建一个resultMap 一对一关系
那个,,,,看完我相信大家也是有点蒙的,,,,,花点时间理解把…
嗯,要不 我们再写一个案例加深印象??
用户信息和订单信息为一对多关系。
同样有俩种解决方案,,,,,第一种使用po类的方法就不演示了
我们使用resultMap来做演示
因为用户是一的一方,所以在一的一方加上多的一方的对象集合,跟hibernate类似,
编写resultMap 以及 sql语句
collection部分定义了用户关联的订单信息。表示关联查询结果集
property=”orders”:关联查询的结果集存储在User对象的上哪个属性。
ofType=”orders”:指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
接口添加方法
测试代码
这里出现卡了很久,原因是 一对一 一对多的 类型 一个使用javaType ,一个是ofType ,这很坑
javaType 表示单个对象, ofType 表示List
2、Mybatis的jar包
3、Spring+mybatis的整合包。
4、Mysql的数据库驱动jar包。
5、数据库连接池的jar包。
jar包自己收集,因为上传文件限制,这里就不能提供了,下面是我导入的所有jar包,是可以运行的,可以当做参考 ……. 注意了,需要特别导入spring + myBatis 的整合jar包
测试代码
因为时间关系,后面内容可能没那么详细,,,,抱歉,,
本章主要讲动态sql,关联查询,spring整合,,如果是初次学习myBatis的同学,请先阅读myBatis入门学习_上
话不多说,上来就是一个需求,惊不惊喜,意不意外 嘿嘿
根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
友情提示- 需要数据的小伙伴请点击myBatis入门学习_上,获取数据库数据…
- 然后粗略的介绍一下Vo,其实就是valueObject的简写,因为select 参数类型只能有一个,我们就是用vo来做数据的存储的…
好了..我们创建一个queryVo
package cn.mybatis.pojo; public class QueryVo { //创建一个user对象 private User user; public void setUser(User user) { this.user = user; } }
然后在配置文件里写sql语句…
<select id="usernameLikeFind" parameterType="cn.mybatis.pojo.QueryVo" resultType="cn.mybatis.pojo.User"> <!--使用ognl从对象中取属性值,如果是包装对象可以使用【属性.XXX.XXX】来取内容的属性--> select * from user where username like '%${user.username}%' </select>
这里使用的是mapper接口方式写代码,就不写实体类了,
userMapper 接口新增方法
public List<User> usernameLikeFind(QueryVo vo);
编写测试代码
SqlSessionFactory factory; InputStream stream; @Before public void createSqlSessionFactory(){ String resources = "mybatisConfig.xml"; //Resources.getResourceAsStream(resources) 这句代码的意思就是查找classpath目录下的mybatisConfig.xml文件 try { stream = Resources.getResourceAsStream(resources); }catch (Exception e){ } SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //获取工厂 factory = builder.build(stream); } 因为没有整合spring,所以我们需要先使用该该方法初始化factory, //测试代码 @Test public void test_fun03(){ //获取session SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = new User(); user.setUsername("小"); QueryVo queryVo = new QueryVo(); queryVo.setUser(user); List<User> users = mapper.usernameLikeFind(queryVo); System.out.println("user="+users); session.close(); }
查询结果如下,
其实动态if啥的没啥好讲的,,看几个案例就懂了,
if语句
小需求 : action 层 传3个值过来,姓名 地址 性别 值可能为null,null 值就不加入查询sql语句中,有7种可能性,如果不使用动态if,那么我们就得写七条sql,,那不是得累死……
有的小伙伴估计要怼我了,,明明就是六种,你硬要说成七种,你是不是傻,,,还有一种可能是就3个值都是null,那就是查询所有
开始写代码把…………先写sql
<select id="queryUserByUsernameAndAddressAndSex" parameterType="cn.mybatis.pojo.User" resultType="cn.mybatis.pojo.User"> <!--基础sql语句--> select * from user WHERE 1 = 1 <!--动态拼接sql --> <if test="username != null"> and username like '%${username}%' </if> <if test="address != null"> and address like '%${address}%' </if> <if test="sex != null"> and sex = '#{sex}' </if> </select>
那个,,, if 有什么作用就不用我来讲了把…….如果真不懂,,那我也没辙了….
接口新增方法…
public List<User> queryUserByUsernameAndAddressAndSex(User user);
测试代码
先测试一波不加参数的, @Test public void test_fun04(){ //获取session SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = new User(); List<User> users = mapper.queryUserByUsernameAndAddressAndSex(user); System.out.println("user="+users); session.close(); }
运行结果是没问题的,
这时可能就有同学不耐烦了,写sql还要加上 where 1 = 1 ,那么麻烦,不学了
4000
别急,myBatis 给我们提供了标签,加上了就不用写了,不信的话我去试试
<select id="queryUserByUsernameAndAddressAndSex" parameterType="cn.mybatis.pojo.User" resultType="cn.mybatis.pojo.User"> <!--基础sql语句--> select * from user <where> <!--动态拼接sql --> <if test="username != null"> and username like '%${username}%' </if> <if test="address != null"> and address like '%${address}%' </if> <if test="sex != null"> and sex = '#{sex}' </if> </where> </select>
然后我这次再加个条件测试一波
@Test public void test_fun04(){ //获取session SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = new User(); user.setSex("1"); List<User> users = mapper.queryUserByUsernameAndAddressAndSex(user); System.out.println("user="+users); session.close(); }
哎呀,,出问题了,,,,但是好像不是标签的问题,去瞄一下sql语句,
<if test="sex != null"> and sex = '#{sex}' </if>
其实使用 #{} 是不能使用引号的,,
然后去掉引号,再测试,
foreach语句
现在action 层又有需求了,传过来一个list集合,要求我们查询id = list里用户id的用户订单,我们先在脑子意淫一下sql 语句
select * from 订单 where 订单.用户id in(a,b,c);
有小伙伴肯定跟我开始想一块了, 把 list遍历一下,然后拼接成字符串 a,b,c 然后把 a,b,c 当成一个参数传过去 /坏笑,这种事想想就好了啊 ahhh
我们在Vo对象里写一个List属性,传的话就传一个Vo过去,,
private List<Integer> users; public void setUsers(List<Integer> users) { this.users = users; }
然后我们来编写sql
<select id="findUserByOrder_uid" resultType="cn.mybatis.pojo.User" parameterType="cn.mybatis.pojo.QueryVo"> select * from user u,orders o where 1 = 1 <!-- (,) --> <foreach collection="users" open="and u.id in (" close=")" item="uid" separator=","> #{uid} </foreach> </select>
嘿嘿,看傻了把, 我来解释一下把
collection=”users”的意思是 遍历 cn.mybatis.pojo.QueryVo 对象里的 users属性,
open=”(” 循环开始符号,
close=”)” 循环结束符号,
item=”uid” 循环的值
separator=”,” 分割符
假如只循环二次 , 一开始产生一个”and id in (“符号,此时 sql语句是这样的
select * from orders o,user u where 1 = 1 and u.id in (
然后拿到值 uid 拼接到sql中去后,sql 语句是这样的
select * from orders o,user u where 1 = 1 and u.id in ( a
然后结束第一次循环,开始第二次,然后sql语句是这样的
select * from orders o,user u where 1 = 1 and u.id in ( a ,
然后又拿到值
select * from orders o,user u where 1 = 1 and u.id in ( a ,b
最后,循环完毕,sql 语句是这样的
select * from orders o,user u where 1 = 1 and id u.in ( a ,b)
接口添加方法
public List<User> findUserByOrder_uid(QueryVo vo);
我们写测试代码测试一下
@Test public void test_fun05(){ //获取session SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); List<Integer> list = Arrays.asList(1, 10, 3); QueryVo queryVo = new QueryVo(); queryVo.setUsers(list); List<Integer> users = mapper.findUserByOrder_uid(queryVo); System.out.println("user="+users); session.close(); }
看看生成的sql语句
sql 片段
我们接下来讲讲sql片段把,,,sql片段其实就是把共性代码抽取出来,然后一起分享使用抽取代码 <sql id="selectXin" > select * </sql> <select id="findUserByOrder_uid" resultType="cn.mybatis.pojo.User" parameterType="cn.mybatis.pojo.QueryVo"> 使用抽取部分 <include refid="selectXin" /> from user u,orders o where 1 = 1 <!-- (,) --> <foreach collection="users" open="and u.id in (" close=")" item="uid" separator=","> #{uid} </foreach> </select>
代码测试
@Test public void test_fun05(){ //获取session SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); List<Integer> list = Arrays.asList(1); QueryVo queryVo = new QueryVo(); queryVo.setUsers(list); List<Integer> users = mapper.findUserByOrder_uid(queryVo); System.out.println("user="+users); session.close(); }
讲的东西有点杂,,,需要好好理一下才行,,最开始我是一脸懵的,,
关联查询
上来反手就是一个需求,嘿嘿案例需求(一对一查询)
查询所有订单信息,关联查询下单用户信息。
需要注意的是,因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单
订单表如下
package com.mybatis.pojo; import java.util.Date; import java.util.List; public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; private User user;//关联映射 public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number == null ? null : number.trim(); } public Date getCreatetime() { return createtime; } public void setC 125de reatetime(Date createtime) { this.createtime = createtime; } public String getNote() { return note; } public void setNote(String note) { this.note = note == null ? null : note.trim(); } }
这里提供俩种方案,
设置返回结果为po类
使用resultMap
方案一
创建一个po类package cn.mybatis.pojo; import java.io.Serializable; //继承order 的属性 public class OrderCustom extends Order implements Serializable{ private String address;// 用户地址 private String username; //姓名 public void setAddress(String address) { this.address = address; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
编写sql
<select id="findAllOrderAndUserInfo" resultType="cn.mybatis.pojo.OrderCustom"> select o.*,u.address,u.username from orders o,user u WHERE o.user_id = u.id; </select>
接口增加方法
public List<OrderCustom> findAllOrderAndUserInfo();
编写测试类
@Test public void test_fun06(){ //获取session SqlSession session = factory.openSession(); OrderMapper mapper = session.getMapper(OrderMapper.class); List<Integer> list = Arrays.asList(1); QueryVo queryVo = new QueryVo(); queryVo.setUsers(list); List<OrderCustom> order = mapper.findAllOrderAndUserInfo(); System.out.println("order="+order); session.close(); }
为了更好的展示运行结果,,我使用debug来截图
方案二
使用resultMap,定义专门的resultMap用于映射一对一查询结果。创建一个resultMap 一对一关系
<resultMap id="findOrderAllUserMap" type="cn.mybatis.pojo.Order"> <!--数据库字段对应表字段--> <id column="id" property="id"></id> <result column="createtime" property="createtime"></result> <result column="number" property="number"></result> <result column="user_id" property="userId"></result> <result column="note" property="note"></result> <!--添加关联关系,javaType="cn.mybatis.pojo.User" user属性对应的类型--> <association property="user" javaType="cn.mybatis.pojo.User"> <id column="userId" property="id"></id> <!--column user表主键对应的列 propertites user具体的属性--> <result column="username" property="username"></result> <result column="address" property="address"></result> </association> </resultMap> <select id="findAllOrderAndUserInfo" resultMap="findOrderAllUserMap"> select o.*,u.address,u.username from orders o,user u where o.user_id = u.id </select>
那个,,,,看完我相信大家也是有点蒙的,,,,,花点时间理解把…
嗯,要不 我们再写一个案例加深印象??
案例需求(一对多查询)
查询所有用户信息,并且关联查询用户下的订单信息。用户信息和订单信息为一对多关系。
同样有俩种解决方案,,,,,第一种使用po类的方法就不演示了
我们使用resultMap来做演示
因为用户是一的一方,所以在一的一方加上多的一方的对象集合,跟hibernate类似,
private List<Order> orders; public void setOrders(List<Order> orders) { this.orders = orders; }
编写resultMap 以及 sql语句
//这里需要注意的是 user表中的主键是id, order表中的主键也是id,如果其中一个id,如果不用别名,,那么会出现数据混乱的情况,所以这里我们order查询出来的id 使用别名oid <resultMap id="findUserAndOrderMap" type="cn.mybatis.pojo.User"> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="birthday" property="birthday"></result> <result column="sex" property="sex"></result> <result column="address" property="address"></result> <!--一对一使用这个--> <!--<association property=""--> <!--一对多使用这个--> <!--<collection property=""--> <collection property="orders" ofType="cn.mybatis.pojo.Order"> <!--这里的oid 使用的是别名--> <id column="oid" property="id"></id> <!--column是列明,properties 是 pojo表中的属性名--> <result column="number" property="number"></result> <result column="createtime" property="createtime"></result> <result column="note" property="note"></result> </collection> </resultMap> <select id="findUserAndOrderInfo" resultMap="findUserAndOrderMap"> select u.* ,o.id oid,o.number,o.note,o.createtime from user u,orders o where u.id = o.user_id; </select>
collection部分定义了用户关联的订单信息。表示关联查询结果集
property=”orders”:关联查询的结果集存储在User对象的上哪个属性。
ofType=”orders”:指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
接口添加方法
public List<User> findUserAndOrderInfo();
测试代码
@Test public void test_fun07(){ //获取session SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); List<User> users = mapper.findUserAndOrderInfo(); System.out.println("user="+users); session.close(); }
这里出现卡了很久,原因是 一对一 一对多的 类型 一个使用javaType ,一个是ofType ,这很坑
javaType 表示单个对象, ofType 表示List
myBatis 整合spring
1.创建一个工程
目录结构如下2.导入jar包
1、spring的jar包2、Mybatis的jar包
3、Spring+mybatis的整合包。
4、Mysql的数据库驱动jar包。
5、数据库连接池的jar包。
jar包自己收集,因为上传文件限制,这里就不能提供了,下面是我导入的所有jar包,是可以运行的,可以当做参考 ……. 注意了,需要特别导入spring + myBatis 的整合jar包
创建配置文件
db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8 jdbc.username=root jdbc.password=itcast
log4j.properties
# Global logging configuration 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
applicationContext.xml
导入约束 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置 数据源 sqlsessionfacotry --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="10" /> <property name="maxIdle" value="5" /> </bean> <!-- sqlsessionfacotry --> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"> <property name="dataSource" ref="dataSource"></property> <!-- mapperLocations指定 :xml的映射文件的位置 ,sql的xml文件的名字和接口的名字一致--> <property name="mapperLocations" value="classpath:mapper/*Mapper.xml" /> </bean> <context:component-scan base-package="com.mybatis.dao"></context:component-scan> <!-- 作用:就是扫描指定的包里面的接口 生成代理对象 它的默认的bean的id 是类名首字母小写 。加载配置文件,要求接口和映射文件在同一个目录,而且名字一致--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.mybatis.dao" /> </bean> </beans>
创建mapper 配置文件
<?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 namespace="com.mybatis.dao.UserMapper"> <select id="com.mybatis.dao.UserMapper" resultType="findAll"> select * from user </select> </mapper>
接口代码 import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface UserMapper { public List<User> findAll(); }
测试代码
@Test public void fun01(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserMapper mapper = context.getBean(UserMapper.class); List<User> all = mapper.findAll(); System.out.println("all"+all); }
输出结果...因为网不好,,图片上传不上来,,就不上传图片了 all[User [id=1, username=王五, sex=2, birthday=null, address=null], User [id=10, username=张三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市], User [id=16, username=张小明, sex=1, birthday=null, address=河南郑州], User [id=22, username=陈小明, sex=1, birthday=null, address=河南郑州], User [id=24, username=张三丰, sex=1, birthday=null, address=河南郑州], User [id=25, username=陈小明, sex=1, birthday=null, address=河南郑州], User [id=26, username=王五, sex=null, birthday=null, address=null], User [id=28, username=李白, sex=男, birthday=Sat Jan 06 00:00:00 CST 2018, address=广东省], User [id=29, username=李白, sex=男, birthday=Sat Jan 06 00:00:00 CST 2018, address=广东省], User [id=30, username=李白, sex=男, birthday=Sat Jan 06 00:00:00 CST 2018, address=广东省]]
因为时间关系,后面内容可能没那么详细,,,,抱歉,,
相关文章推荐
- MyBatis学习总结(一)——MyBatis快速入门【转】
- MyBatis学习总结(一)——MyBatis快速入门
- MyBatis入门学习(一)
- MyBatis学习入门_01
- MyBatis学习总结(1)——MyBatis快速入门
- MyBatis入门学习教程-MyBatis快速入门
- 《Spring+Mybatis》Mybatis入门学习笔记与代码
- Mybatis入门学习(一)
- Mybatis入门学习(三)
- MyBatis学习总结[1]-入门
- MyBatis学习之入门篇
- MyBATIS3入门学习笔记
- 【新技术,学习、商业均可】HTML5 全新高大尚后台 bootstrap springmvc mybatis java企业级通框架源码入门
- Mybatis学习笔记-入门
- MyBatis入门学习(一)
- MyBatis学习总结(一)——MyBatis快速入门
- Mybatis学习--入门
- MyBatis入门学习By项目一
- MyBatis学习之入门 (一)
- MyBatis学习总结(1)——MyBatis快速入门