MyBatis--第三天
来源:互联网 发布:android 棋牌游戏源码 编辑:程序博客网 时间:2024/05/21 20:27
1 动态sql
1.1 什么是动态sql
mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。
需求:根据用户的名字的模糊匹配和性别查询
<select id="findByNameAndSex" parameterType="com.demo3.UserQuery" resultType="com.demo3.User_tbCustomer">
select * from user_tb where 1=1
<if test="user_tbCustomer!=null anduser_tbCustomer.name!=null and user_tbCustomer.name!=''">
and name like '%${user_tbCustomer.name}%'
</if>
<if test="user_tbCustomer!=null and user_tbCustomer.sex!=null and user_tbCustomer.sex!=''">
and sex=#{user_tbCustomer.sex}
</if>
</select>
改进:
<select id="findByNameAndSex" parameterType="com.demo3.UserQuery" resultType="com.demo3.User_tbCustomer">
select * from user_tb
<where> <!-- where自动添加而且去掉第一个and -->
<if test="user_tbCustomer!=null and user_tbCustomer.name!=null and user_tbCustomer.name!=''">
and name like '%${user_tbCustomer.name}%'
</if>
<if test="user_tbCustomer!=null and user_tbCustomer.sex!=null and user_tbCustomer.sex!=''">
and sex=#{user_tbCustomer.sex}
</if>
</where>
</select>
接口方法:public List<User_tbCustomer> findByNameAndSex(UserQuery userQuery);
测试
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
User_tbMapper user_tbMapper = sqlsession.getMapper(User_tbMapper.class);
User_tbCustomer user_customer=new User_tbCustomer();
user_customer.setName("张"); //关闭该功能测试
user_customer.setSex("男"); ////关闭该功能测试
UserQuery uq=new UserQuery();
uq.setUser_tbCustomer(user_customer);
List<User_tbCustomer> list = user_tbMapper.findByNameAndSex(uq);
System.out.println(list.size());
1.2 sql片段
1.2.1 需求
将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段。
方便程序员进行开发。
1.2.2 定义和引用sql片段
在mapper.xml中
<select id="findByNameAndSex" parameterType="com.demo3.UserQuery" resultType="com.demo3.User_tbCustomer">
select * from user_tb
<!-- 引用sql片段 -->
<include refid="user_where"></include>
</select>
<!-- 封装sql条件,以便重用 -->
<sql id="user_where">
<where> <!-- where自动添加而且去掉第一个and -->
<if test="user_tbCustomer.name!=null and user_tbCustomer.name!=''">
and name like '%${user_tbCustomer.name}%'
</if>
<if test="user_tbCustomer.sex!=null and user_tbCustomer.sex!=''">
and sex=#{user_tbCustomer.sex}
</if>
</where>
</sql>
1.3 foreach
向sql传递数组或List,mybatis使用foreach解析
1.3.1 需求
查询id为1或者10或者16的用户信息
两种方法:
SELECT * FROM user_tb WHERE id=1 OR id=10 OR id=16 (不效率)
SELECT * FROM user_tb WHERE id IN(1,10,16)
步骤:
1 在包装类中封装一个List<Integer>
private List<Integer>ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
2 mapper.xml中
<select id="findByIds" parameterType="com.demo3.UserQuery" resultType="com.demo3.User_tbCustomer">
select * from user_tb
<where>
<if test="ids!=null and ids!=''">
<!--
collection:集合名
item:代表遍历中的每个元素
open:以..开始
close:以..结束
separator:分隔符
-->
<foreach collection="ids" item="id" open="id in (" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
3 接口
public List<User_tbCustomer> findByIds(UserQuery userQuery);
2 测试
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
User_tbMapper user_tbMapper = sqlsession.getMapper(User_tbMapper.class);
UserQuery uq=new UserQuery();
List<Integer> ids=new ArrayList<Integer>();
ids.add(1);
ids.add(4);
ids.add(11);
ids.add(17);
uq.setIds(ids);
List<User_tbCustomer> list = user_tbMapper.findByIds(uq);
System.out.println(list.size());
现在有两张表
订单表 order_tb
id createtime uid
客户表user_tb
id name sex birthday address
分析关系:1个客户可以有多个订单 ,而一个订单只能被一个客户拥有
多:订单 ----- 一:客户
以前的hibernate:学生和专业
学生为多 :在学生实体类中封装一个专业对象
专业为一:在专业实体类中封装一个set集合
目的:查出两张表所有数据
多对一:
在mybatis中的配置:
方法1:自动映射:resultType
在java中:由于查的数据来自于两张表,我们实际的做法:
1 分别写两个bean:User_tb Order_tb
2 写一个扩展类继承属性多的那个bean,然后在属性中对另一个属性少的bean的属性封装get和set
如:
3 在mapper.xml中
<select id="findOrderAndUser1" resultType="com.demo3.User_tbCustomer">
select u.*,o.id as 'oid',o.createtime,o.uid from user_tb u,order_tb o where o.uid=u.id
</select>
4 mapper接口中:
public List<User_tbCustomer> findOrderAndUser1();
5 测试:
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
User_tbMapper user_tbMapper = sqlsession.getMapper(User_tbMapper.class);
List<User_tbCustomer> list = user_tbMapper.findOrderAndUser1();
for(User_tbCustomer uc:list){
System.out.println(uc.getId()+uc.getName()+uc.getSex()+uc.getBirthday()+uc.getAddress()+"--"+uc.getOid()+uc.getCreatetime()+uc.getUid());
}
注意:
这样查出的订单对象是null,只能写具体的属性,不能封装对象
方法2:手动映射
回顾hibernate的学生和科目 是在学生类中写了一个Major major对象去替换以前的majorid
而在mybatis中,uid(外键)不能省
步骤:
1 在 Order_tb中封装User_tb,但Order_tb中的uid也不能省
2 mapper.xml
<!--
type:最终输出的类型
id:唯一标识
-->
<resultMap type="com.beans.Order_tb" id="orderAndUserResultMap">
<id column="oid" property="id"/>
<result column="createtime" property="createtime"/>
<result column="uid" property="uid"/>
<!--
association针对对象的映射 多对1
property:属性名(该对象名)
javaType:属性类型
-->
<association property="user_tb" javaType="com.beans.User_tb">
<!-- 由于我在多表查询中该用户的id查了两次(u.*和o.uid),所有这里column可以写id或uid -->
<id column="uid" property="id"/>
<result column="name" property="name"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="findOrderAndUser2" resultMap="orderAndUserResultMap">
select u.*,o.id as 'oid',o.createtime,o.uid from user_tb u,order_tb o where o.uid=u.id
</select>
Association可以看做hibernate的many-to-one
3 mapper接口public List<Order_tb> findOrderAndUser2();
4 测试
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
User_tbMapper user_tbMapper = sqlsession.getMapper(User_tbMapper.class);
List<Order_tb> list = user_tbMapper.findOrderAndUser2();
for(Order_tb o:list){
System.out.println(o.getId()+" "+o.getUser_tb().getName());
}
一对多:
如果是1对多,则需要在user_tb中添加order_tb集合,
既然是集合,则无法用多对一的 resultRype的方法:因为该方法是多对一,在多的实体类(order_tb)中封装一个一的(User_tb)的属性(get和set),因为只有一个,而一对多,有多个,封装属性是不对的(你不可能封装多个相同属性)
所以,只能用ResultMap的方法
步骤:
1 在User_tb中封装List<Order_tb>(get和set)
2 在mapper.xml
<!--
type:最终输出的类型
id:唯一标识
-->
<resultMap type="com.beans.User_tb" id="orderAndUserResultMap2">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<!--
collection 针对对象的映射1对多
property 属性名(集合名)
ofType:集合中的类型
-->
<collection property="olist" ofType="com.beans.Order_tb">
<id column="oid" property="id"/>
<result column="createtime" property="createtime"/>
<result column="uid" property="uid"/>
</collection>
</resultMap>
<select id="findOrderAndUser3" resultMap="orderAndUserResultMap2">
select u.*,o.id as 'oid',o.createtime,o.uid from user_tb u,order_tb o where o.uid=u.id
</select>
3 mapper接口:
public List<User_tb> findOrderAndUser3();
4测试:
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
User_tbMapper user_tbMapper = sqlsession.getMapper(User_tbMapper.class);
List<User_tb> list = user_tbMapper.findOrderAndUser3();
for(User_tb u:list){
System.out.println(u.getName()+" "+u.getOlist().size());
}
比较hibernate 和 mybatis
Mybatis的关系映射比hibernate难写,但效率高
resultMap可以实现延迟加载,resultType无法实现延迟加载。
- mybatis开发(第三天)
- MyBatis--第三天
- MyBatis学习总结--第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- 第三天
- [云路由器] 设置了虚拟服务器,外网无法访问服务器怎么办?
- Android开源库V
- php下pgsql扩展安装
- typeof、undefined,一个易犯的错误
- 远程操作SDR实现
- MyBatis--第三天
- 分页查询,天坑一枚
- cf424div2 A. Unimodal Array
- 23种设计模式之——单例模式
- 玩过狼人杀吗
- IT行业、前端、java入门必备书籍
- usart&spi
- Unity—UI正对摄像机
- NSTimer的使用(精简)