本文共 8601 字,大约阅读时间需要 28 分钟。
标签: Java与存储
动态SQL提供了对SQL语句的灵活操作,通过表达式进行判断,对SQL进行拼接/组装.
对查询条件进行判断,如果输入参数不为空才进行查询条件的拼接.
<where/>
会自动处理第一个AND
(MyBatis还提供了自定义<where/>
行为的<trim/>
元素, 详细可参考).
ListselectUser(User user) throws Exception;
@Testpublic void selectUserClient() throws Exception { UserDAO dao = session.getMapper(UserDAO.class); User user = dao.selectUser(new User(null, null, "new_password")); System.out.println(user);}
由于id与name为
null
, 因此这两个条件不会拼接在SQL中,这一点可以调试时日志中看出.
有些时候,我们并不想用到所有的条件语句,而只想从中选择一二.针对这种情况,MyBatis提供了<choose/>
元素,他有点像Java中的switch
.
用于动态更新语句的解决方案为<set/>
,set元素可以被用于动态包含需要更新的列, 而舍去其他的.
UPDATE user WHERE id = #{id}; name = #{name} , password = #{password} ,
使用foreach可以实现向SQL中传递数组或List
:
查询多个id的用户信息, 可以由下面两种SQL实现:
SELECT * FROM user WHERE (id = ? OR id = ? OR id = ?);SELECT * FROM user WHERE id IN (?, ?, ?, ?);
因此其foreach的定义也有如下两种方案:
元素 | 描述 |
---|---|
collection | SQL解析的参数名 |
index | 循环下标 |
item | 单个元素的名 |
open | 循环开始输出 |
close | 循环结束输出 |
separator | 中间分隔输出 |
传递
List
作为parameterType
时,SQL解析参数名固定为list
.
ListselectUser(List ids) throws Exception;
INSERT INTO user(name, password) VALUES (#{user.name}, #{user.password})
void insertUserList(Listusers) throws Exception;
@Testpublic void insertUserListClient() throws Exception { UserDAO dao = session.getMapper(UserDAO.class); dao.insertUserList(Lists.newArrayList(new User(null, "mojia5", "mojia5"), new User(null, "mojia6", "mojia6"), new User(null, "mojia7", "mojia7")));}
与
List
类似,传递数组作为parameterType
时,SQL解析参数名固定为array
.
ListselectUser(Integer[] ids) throws Exception;
可以将一段公共的SQL语句抽取出来, 作为一个SQL片段, 供其他SQL调用:
AND id = #{id} AND name = #{name} AND password = #{password}
经验:最好基于单表定义SQL片段,而且在SQL片段中不要包含
<where>
/<set>
之类的标签,这样可以保证SQL片段重用度更高.
数据模型分析思路
订单/商品数据模型
需求: 查询订单信息,关联查询(创建订单的)用户信息.
由以上分析可知主查询为order
表,而order -> user
关系为一对一, 因此使用resultMap
将查询结果的订单信息映射到Order
中,将用户信息映射到Order
中的User
属性.
User
public class User implements Serializable { private Integer id; private String username; private Date birthday; private Integer sex; private String address; // ...}
Order
, 将User
组合到Order
中:public class Order implements Serializable { private Integer id; private Integer userId; private String number; private Date createTime; private String note; private User user; // ...}
association
: 映射关联查询的单条记录(将关联查询信息映射到PO对象属性).
public interface OrderDAO { Order selectOrderWithUser(Integer id) throws Exception;}
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring/applicationContext.xml")public class OrderDAOClient { @Autowired private OrderDAO dao; @Test public void client() throws Exception { Order order = dao.selectOrderWithUser(3); System.out.println(order); }}
需求: 查询订单及订单明细的信息(一对多).
OrderDetail
,并在Order
中添加List<OrderDetail> orderDetails
订单明细属性:public class OrderDetail implements Serializable { private Integer id; private Integer orderId; private Integer itemId; private Integer itemNumber; // ...}
元素 | 描述 |
---|---|
property | 指定关联查询的结果集存储到的属性 |
ofType | 指定关联查询结果集中的对象类型 |
Order selectOrderWithDetail(Integer id) throws Exception;
需求: 查询用户及用户购买商品信息.
由于User表与Item表没有直接关联,因此只能通过Order表与OrderDetail表进行关联.
思路:
1) 将用户信息映射到User
中. 2) 在User
中添加List<Order>
订单列表属性,将用户创建的订单映射到orders
. 3) 在Order
中添加List<OrderDetail>
订单明细列表属性,将订单的明细映射到orderDetails
. 4) 在OrderDetail
中添加Item
属性,将订单明细所对应的商品映射到item
.PO: Item
public class Item { private Integer id; private String name; private Float price; private String detail; private String pic; private Date createTime; //...}
ListselectUserItem() throws Exception;
使用<association/>
和<collection/>
可以完成一对一和一对多的高级映射.
关联查询时,使用MyBatis 延迟加载 特性可有效减轻数据库压力.首次查询只查询主表信息,等需要时再去查询关联表信息.<resultMap/>
的<association/>
/<collection/>
具备延迟加载功能.
需求: 查询订单信息并关联查询用户信息.
在MyBatis核心配置文件(mybatis-configuration.xml)中配置:
1)lazyLoadingEnabled
: 设置是否懒加载.默认false
,则所有关联查询都会被初始化加载. 2) aggressiveLazyLoading
: 设置是否积极加载. 默认true
,所有关联属性被初始化加载.Settings配置:
元素 | 描述 |
---|---|
select | 指定关联查询Statement为com.fq.mybatis.UserDAO.selectUserById . |
column | 指定关联查询时将users_id 值传入selectUserById . |
com.fq.mybatis.UserDAO
)将上面查询到的订单信息中的
user_id
传入selectUserById
来关联查询用户信息.
ListselectOrderWithUser() throws Exception;
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring/applicationContext.xml")public class OrderDAOClient { @Autowired private OrderDAO dao; @Test public void client() throws Exception { Listorders = dao.selectOrderWithUser(); for (Order order : orders) { System.out.println(order.getUser()); } }}
debug上面
Client
, 观察log信息,会发现只有当确实需要User
信息时才会调用selectUserById
.
转载地址:http://vxsux.baihongyu.com/