回顧
1. 嵌套查詢(xún)
將多表的聯(lián)合抒钱,拆成多個(gè)單表查詢(xún)衡创,在通過(guò)mybatis嵌套組合
步驟:一對(duì)一舉例
1)根據(jù)訂單id查詢(xún)訂單
2)根據(jù)訂單uid查詢(xún)用戶(hù)
3)最后由mybatis嵌套組合
2. 加載策略
模型在關(guān)聯(lián)時(shí),是否要查詢(xún)所管理的數(shù)據(jù)模型
立即加載:一對(duì)一
延遲加載:一對(duì)多、多對(duì)多
3. 緩存機(jī)制
提高查詢(xún)效率
一級(jí)緩存:不需要我們做任何配置,底層就是map集合
二級(jí)緩存:需要在映射文件配置<cache></cache> ,給實(shí)體類(lèi)實(shí)現(xiàn)序列化接口【了解】
4. 核心配置文件回顧
所有的配置文件记靡,每一個(gè)標(biāo)簽必須加中文注釋...
MyBatis注解&綜合練習(xí)
今日目標(biāo)
1. 注解開(kāi)發(fā)
單表【重點(diǎn)】
多表【了解】
2. 綜合案例練習(xí)
查詢(xún)所有
分頁(yè)查詢(xún)【重點(diǎn):3遍】
一 MyBatis注解
? 這幾年來(lái)注解開(kāi)發(fā)越來(lái)越流行,Mybatis也可以使用注解開(kāi)發(fā)方式团驱,這樣我們就可以減少編寫(xiě)Mapper映射文件了摸吠。我們先圍繞一些基本的CRUD來(lái)學(xué)習(xí),再學(xué)習(xí)復(fù)雜映射多表操作嚎花。
1.1 MyBatis常用注解
* @Insert:實(shí)現(xiàn)新增寸痢,代替了<insert></insert>
* @Update:實(shí)現(xiàn)更新,代替了<update></update>
* @Delete:實(shí)現(xiàn)刪除紊选,代替了<delete></delete>
* @Select:實(shí)現(xiàn)查詢(xún)啼止,代替了<select></select>
* @Result:實(shí)現(xiàn)結(jié)果集封裝道逗,代替了<result></result>
* @Results:可以與@Result 一起使用,封裝多個(gè)結(jié)果集献烦,代替了<resultMap></resultMap>
* @One:實(shí)現(xiàn)一對(duì)一結(jié)果集封裝滓窍,代替了<association></association>
* @Many:實(shí)現(xiàn)一對(duì)多結(jié)果集封裝,代替了<collection></collection>
環(huán)境搭建
1.2 MyBatis單表操作【重點(diǎn)】
需求:基于user模塊通過(guò)注解實(shí)現(xiàn)巩那,增刪改查
① UserMapper接口
public interface UserMapper {
// 查詢(xún)所有
@Select("select id as uid,username as uname,birthday as bir , sex as gender, address as addr from user")
@Results({ // resultMap標(biāo)簽手動(dòng)映射
@Result(column = "uid",property = "id",id=true), // result標(biāo)簽映射封裝
@Result(column = "uname",property = "username"),
@Result(column = "bir",property = "birthday"),
@Result(column = "gender",property = "sex"),
@Result(column = "addr",property = "address")
})
public List<User> findAll();
// id查詢(xún)
@Select("select * from user where id = #{id}")
public User findById(Integer id);
// 新增
@Insert("insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")
public void save(User user);
// 修改(動(dòng)態(tài)sql還是推薦使用xml)
@Update("update user set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address} where id = #{id}")
public void update(User user);
// 刪除
@Delete("delete from user where id = #{id}")
public void delete(Integer id);
}
② 測(cè)試
public class UserMapperTest extends BaseMapperTest {
// 單表測(cè)試
@Test
public void test01() throws Exception {
// 獲取代理對(duì)象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 查詢(xún)所有
List<User> list = userMapper.findAll();
System.out.println(list);
// 查詢(xún)一個(gè)
/* User user = userMapper.findById(41);
System.out.println(user);*/
// 新增
/* User user = new User();
user.setUsername("吉克雋逸");
user.setBirthday(new Date());
user.setSex("女");
user.setAddress("彝族....");
userMapper.save(user);*/
// 更新
/* User user = new User();
user.setId(53);
user.setUsername("迪麗熱巴");
user.setBirthday(new Date());
user.setSex("女");
user.setAddress("新疆....");
userMapper.update(user);*/
// 刪除
// userMapper.delete(53);
}
}
1.3 MyBatis多表操作【了解】
注解多表操作是基于嵌套查詢(xún)來(lái)實(shí)現(xiàn)
1.3.1 一對(duì)一查詢(xún)
需求:查詢(xún)一個(gè)訂單吏夯,與此同時(shí)查詢(xún)出該訂單所屬的用戶(hù)
一對(duì)一查詢(xún)語(yǔ)句
SELECT * FROM orders where id = #{id};
SELECT * FROM `user` WHERE id = #{訂單的uid};
① OrderMapper接口
public interface OrderMapper {
// 一對(duì)一嵌套注解
@Select("select * from orders where id = #{id}")
@Results({
@Result(column = "id",property = "id",id=true),
@Result(column = "ordertime",property = "ordertime"),
@Result(column = "money",property = "money")
})
public Order findByIdWithUser(Integer id);
}
② UserMapper接口
public interface UserMapper {
// id查詢(xún)
@Select("select * from user where id = #{id}")
public User findById(Integer id);
}
③ 注解嵌套
④ 測(cè)試
public class OrderMapperTest extends BaseMapperTest { // 繼承父類(lèi),就可以直接使用 父類(lèi)的方法和成員變量了
// 一對(duì)一嵌套測(cè)注解試
@Test
public void test01() throws Exception {
// 獲取代理對(duì)象
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
// 根據(jù)id查詢(xún)
Order order = orderMapper.findByIdWithUser(1);
System.out.println(order);
}
}
1.3.2 一對(duì)多查詢(xún)
需求:查詢(xún)一個(gè)用戶(hù)拢操,與此同時(shí)查詢(xún)出該用戶(hù)具有的訂單
一對(duì)多查詢(xún)語(yǔ)句
SELECT * FROM `user` where id = #{id};
SELECT * FROM orders where uid = #{用戶(hù)id};
① UserMapper接口
public interface UserMapper {
// 一對(duì)多注解嵌套查詢(xún)
@Select("select * from user where id = #{id}")
@Results({ // resultMap標(biāo)簽手動(dòng)映射
@Result(column = "id",property = "id",id=true), // result標(biāo)簽映射封裝
@Result(column = "username",property = "username"),
@Result(column = "birthday",property = "birthday"),
@Result(column = "sex",property = "sex"),
@Result(column = "address",property = "address")
})
public User findByIdWithOrders(Integer id);
}
② OrderMapper接口
public interface OrderMapper {
@Select("select * from orders where uid = #{id}")
public List<Order> findByUid(Integer uid);
}
③ 注解嵌套
④ 測(cè)試
// 一對(duì)多注解測(cè)試
@Test
public void test02() throws Exception {
// 獲取代理對(duì)象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findByIdWithOrders(41);
System.out.println(user);
System.out.println(user.getOrderList());
}
1.3.3 多對(duì)多查詢(xún)
需求:查詢(xún)用戶(hù)同時(shí)查詢(xún)出該用戶(hù)的所有角色
多對(duì)多查詢(xún)語(yǔ)句
SELECT * FROM `user` where id = #{id};
SELECT * FROM role r INNER JOIN user_role ur ON r.`id` = ur.`rid`
WHERE ur.`uid` = #{用戶(hù)id};
① UserMapper接口
public interface UserMapper {
// 多對(duì)多注解嵌套查詢(xún)
@Select("select * from user where id = #{id}")
@Results({ // resultMap標(biāo)簽手動(dòng)映射
@Result(column = "id",property = "id",id=true), // result標(biāo)簽映射封裝
@Result(column = "username",property = "username"),
@Result(column = "birthday",property = "birthday"),
@Result(column = "sex",property = "sex"),
@Result(column = "address",property = "address")
})
public User findByIdWithRoles(Integer id);
}
② RoleMapper接口
public interface RoleMapper {
@Select("SELECT * FROM role r INNER JOIN user_role ur ON ur.`rid` = r.`id` WHERE ur.`uid` =#{uid}")
@Results({
@Result(column = "id",property = "id",id=true),
@Result(column = "role_name",property = "roleName"),
@Result(column = "role_desc",property = "roleDesc")
})
public List<Role> findByUid(Integer uid);
}
③ 注解嵌套
④ 測(cè)試
// 多對(duì)多注解測(cè)試
@Test
public void test03()throws Exception{
// 獲取代理對(duì)象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findByIdWithRoles(41);
System.out.println(user);
System.out.println(user.getRoleList());
}
1.4 局部延遲加載
不管是一對(duì)多還是多對(duì)多 锦亦,在注解配置中都有fetchType的屬性
* fetchType = FetchType.LAZY 表示懶加載
* fetchType = FetchType.EAGER 表示立即加載
* fetchType = FetchType.DEFAULT 表示使用全局配置
1.5 二級(jí)緩存
配置SqlMapConfig.xml文件開(kāi)啟二級(jí)緩存的支持
<settings>
<!--
因?yàn)閏acheEnabled的取值默認(rèn)就為true,所以這一步可以省略不配置令境。
為true代表開(kāi)啟二級(jí)緩存;為false代表不開(kāi)啟二級(jí)緩存顾瞪。
-->
<setting name="cacheEnabled" value="true"/>
</settings>
在Mapper接口中使用注解配置二級(jí)緩存
@CacheNamespace
public interface UserMapper {...}
1.6 知識(shí)小結(jié)
1. 注解開(kāi)發(fā)和xml配置相比舔庶,從開(kāi)發(fā)效率來(lái)說(shuō),注解編寫(xiě)更簡(jiǎn)單陈醒,效率更高惕橙。
2. 從可維護(hù)性來(lái)說(shuō),注解如果要修改钉跷,必須修改源碼弥鹦,會(huì)導(dǎo)致維護(hù)成本增加。xml維護(hù)性更強(qiáng)爷辙。
* 經(jīng)驗(yàn):?jiǎn)伪砗?jiǎn)單CRUD可以使用注解彬坏、多表及動(dòng)態(tài)sql你就用xml
二 MyBatis案例練習(xí)
2.1 編程風(fēng)格
瀏覽器:Chrome、Firefox
包目錄:cn(com).公司名.項(xiàng)目名(都是小寫(xiě))
類(lèi):大駝峰式命名
方法名:小駝峰式命名
帥哥用啥你用啥膝晾,帥哥寫(xiě)啥你寫(xiě)啥
2.2 環(huán)境搭建
① 準(zhǔn)備數(shù)據(jù)庫(kù)和表
② 創(chuàng)建web工程栓始,導(dǎo)入jar包
③ 導(dǎo)入頁(yè)面資源
④ 創(chuàng)建三層包結(jié)構(gòu)
⑤ 導(dǎo)入mybatis相關(guān)初始化配置
⑥ 編寫(xiě)中文過(guò)濾器
@WebFilter("/*")
public class EncodeFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {
// 接收請(qǐng)求字符集
servletRequest.setCharacterEncoding("utf-8");
// 放行
chain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}
⑦ 測(cè)試環(huán)境
2.3 查詢(xún)所有
2.3.1 需求和效果實(shí)現(xiàn)
通過(guò)三層架構(gòu)+接口+mybatis,查詢(xún)員工信息血当,在頁(yè)面展示
2.3.2 需求分析
2.3.3 代碼實(shí)現(xiàn)
① index.jsp
<a href="${pageContext.request.contextPath}/EmpServlet?action=findAll">員工列表</a>
② Emp實(shí)體類(lèi)
public class Emp {
private Integer id;
private String ename;
private String sex;
private String joindate; // 通過(guò)字符串也可以表示日期
private Double salary;
private String address;
}
③ EmpServlet
@WebServlet("/EmpServlet")
public class EmpServlet extends HttpServlet {
// 重寫(xiě)service方法
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 獲取action請(qǐng)求參數(shù)
String action = request.getParameter("action");
// 判斷
if (action.equals("findAll")) {
this.findAll(request, response);
}
}
// 查詢(xún)所有
protected void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.調(diào)用service查詢(xún)
EmpService empService = new EmpServiceImpl();
List<Emp> list = empService.findAll();
// 2.將list寫(xiě)入request域
request.setAttribute("list", list);
// 3.轉(zhuǎn)發(fā)
request.getRequestDispatcher("/list.jsp").forward(request, response);
}
}
④ EmpServiceImpl
public class EmpServiceImpl implements EmpService {
@Override
public List<Emp> findAll() {
// 通過(guò)mybatis工具類(lèi)獲取sqlSession
SqlSession sqlSession = MyBatisUtils.openSession();
// 創(chuàng)建EmpDao代理對(duì)象
EmpDao empDao = sqlSession.getMapper(EmpDao.class);
// 查詢(xún)
List<Emp> list= empDao.findAll();
// 關(guān)閉sqlSession
MyBatisUtils.close(sqlSession);
return list;
}
}
⑤ EmpDao(接口+映射)
⑥ list.jsp
<c:forEach items="${list}" var="emp">
<tr>
<td>${emp.id}</td>
<td>${emp.ename}</td>
<td>${emp.joindate}</td>
<td>${emp.salary}</td>
<td>${emp.address}</td>
</tr>
</c:forEach>
2.4 分頁(yè)查詢(xún)【重點(diǎn)☆☆☆☆】
2.4.1 導(dǎo)入數(shù)據(jù)
insert into `emp`(`id`,`ename`,`sex`,`joindate`,`salary`,`address`) values(6,'王昭君','女','2010-12-17',28500,'北京'),(7,'劉備','男','2014-07-18',24500,'廣州'),(8,'小二郎','男','2004-11-23',30000,'廣州'),(9,'小龍女','女','2009-05-18',50000,'深圳'),(10,'貂蟬','女','2014-07-30',15000,'深圳'),(11,'劉三','男','2019-06-23',11000,'上海'),(12,'李逵','男','2012-07-05',9500,'廣州'),(13,'李楠','女','2012-07-05',11500,'北京'),(14,'小白龍','男','2011-09-18',30000,'深圳'),(15,'西施','女','2015-07-06',13000,'北京'),(16,'劉茹','女','2019-08-07',6000,'北京');
2.4.2 分頁(yè)介紹
在實(shí)際開(kāi)發(fā)中幻赚,如果數(shù)據(jù)庫(kù)數(shù)據(jù)太多,一般我們需要進(jìn)行分頁(yè)查詢(xún)臊旭,提高效率...
分頁(yè)技術(shù)實(shí)現(xiàn)
物理分頁(yè):數(shù)據(jù)庫(kù)實(shí)現(xiàn)(MySQL落恼、Oracle)
內(nèi)存分頁(yè):查詢(xún)?nèi)浚谕ㄟ^(guò)java代碼進(jìn)行分頁(yè)
今天我們來(lái)使用MySQL操作物理分頁(yè)
* 語(yǔ)法:
select * from 表名 limit 開(kāi)始索引,每頁(yè)個(gè)數(shù);
* 模擬百度分頁(yè)离熏,一個(gè)顯示5條佳谦,數(shù)據(jù)庫(kù)共有16條記錄
第一頁(yè)
select * from 表名 limit 0,5;
第二頁(yè)
select * from 表名 limit 5,5;
第三頁(yè)
select * from 表名 limit 10,5;
第四頁(yè)
select * from 表名 limit 15,5;
* 索引公式
開(kāi)始索引=(當(dāng)前頁(yè)-1) × 每頁(yè)個(gè)數(shù)
* 如何獲得當(dāng)前頁(yè)和每頁(yè)個(gè)數(shù)?
前端頁(yè)提供的
2.4.3 需求和效果實(shí)現(xiàn)
通過(guò)mysql物理分頁(yè)撤奸,一個(gè)顯示5條吠昭,數(shù)據(jù)庫(kù)共有16條記錄
2.4.3 需求分析
后端代碼流程圖
2.4.4 代碼實(shí)現(xiàn)
① index.jsp
② PageBean
public class PageBean<E> {
private Integer totalCount; // 總記錄數(shù)
private Integer totalPage;// 總頁(yè)數(shù)
private List<E> list; // 結(jié)果集
private Integer currentPage; // 當(dāng)前頁(yè)
private Integer pageSize; // 每頁(yè)個(gè)數(shù)
}
③ EmpServlet
EmpService empService = new EmpServiceImpl();
// 分頁(yè)查詢(xún)
protected void findByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收請(qǐng)求參數(shù)
String currentPageStr = request.getParameter("currentPage");
String pageSizeStr = request.getParameter("pageSize");
// 2.轉(zhuǎn)為整型
int currentPage = Integer.parseInt(currentPageStr);
int pageSize = Integer.parseInt(pageSizeStr);
// 3.調(diào)用service查詢(xún)
PageBean<Emp> pb = empService.findByPage(currentPage, pageSize);
// 4.設(shè)置到request域
request.setAttribute("pb", pb);
// 5.轉(zhuǎn)發(fā)
request.getRequestDispatcher("/list.jsp").forward(request, response);
}
④ EmpServiceImpl
@Override
public PageBean<Emp> findByPage(int currentPage, int pageSize) {
// 通過(guò)mybatis工具類(lèi)獲取sqlSession
SqlSession sqlSession = MyBatisUtils.openSession();
// 創(chuàng)建EmpDao代理對(duì)象
EmpDao empDao = sqlSession.getMapper(EmpDao.class);
// 1.創(chuàng)建 PageBean
PageBean<Emp> pageBean = new PageBean<>();
// 2.封裝當(dāng)前頁(yè)和每頁(yè)個(gè)數(shù)
pageBean.setCurrentPage(currentPage);
pageBean.setPageSize(pageSize);
// 3.調(diào)用dao查詢(xún)總記錄數(shù)并封裝
Integer totalCount = empDao.findCount();
pageBean.setTotalCount(totalCount);
// 4.計(jì)算并封裝總頁(yè)數(shù)
int totalPage = (int)Math.ceil(totalCount * 1.0/ pageSize);
pageBean.setTotalPage(totalPage);
// 5.計(jì)算開(kāi)始索引
int index = (currentPage - 1) * pageSize;
// 6.調(diào)用dao查詢(xún)結(jié)果集并封裝
List<Emp> list = empDao.findList(index,pageSize);
pageBean.setList(list);
// 關(guān)閉sqlSession
MyBatisUtils.close(sqlSession);
// 7.返回pageBean對(duì)象
return pageBean;
}
⑤ EmpDao(接口+映射)
⑥ list.jsp
<body>
<table border="1" cellpadding="0" cellspacing="0" width="600px">
<tr>
<td>姓名</td>
<td>性別</td>
<td>入職日期</td>
<td>薪資</td>
<td>住址</td>
</tr>
<c:forEach items="${pb.list}" var="emp">
<tr>
<td>${emp.id}</td>
<td>${emp.ename}</td>
<td>${emp.joindate}</td>
<td>${emp.salary}</td>
<td>${emp.address}</td>
</tr>
</c:forEach>
</table>
<table>
<tr>
<td style="text-align: left">總共檢索到${pb.totalCount}條記錄,共分${pb.totalPage}頁(yè)</td>
</tr>
</table>
<table id="page">
<tr>
<c:if test="${pb.currentPage>1}">
<td style="width:50px">
<a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage¤tPage=${pb.currentPage-1}&pageSize=5">上一頁(yè)</a>
</td>
</c:if>
<c:forEach begin="1" end="${pb.totalPage}" var="page">
<c:if test="${page == pb.currentPage}">
<td bgcolor="#ffd700">
<a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage¤tPage=${page}&pageSize=5">${page}</a>
</td>
</c:if>
<c:if test="${page != pb.currentPage}">
<td>
<a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage¤tPage=${page}&pageSize=5">${page}</a>
</td>
</c:if>
</c:forEach>
<c:if test="${pb.currentPage < pb.totalPage}">
<td style="width:50px">
<a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage¤tPage=${pb.currentPage+1}&pageSize=5">下一頁(yè)</a>
</td>
</c:if>
</tr>
</table>
</body>
總結(jié)
1. mybatis注解 晚上敲
單表【重點(diǎn)】
@Insert
@Update
@Delete
@Select
@Results
@Result
多表【休息日再敲....】
2. 綜合案例 下午敲
編程風(fēng)格(跟帥哥一致...)
環(huán)境搭建
查詢(xún)所有
JDBC
分頁(yè)查詢(xún)【晚上敲】
3. 明天課程非常輕松...