Mybatis:
今天上午,讲了Mybatis里的多表连接查询,包括一对一和一对多。
涉及到两个表:
customer表:
orders表:
从表中我们可以看到,orders表中有一个外键:customer_id,这个外键是customer表的主键。
首先来看一对一的内连接查询,根据订单表的id查出该订单的所有信息以及该订单所属的客户信息。一条订单的记录对应于一个客户,所以这是一对一的表关联查询。
sql语句:
select c.id cid,c.name,c.age,o.id oid,o.orderNumber,o.orderPrice
from orders o inner join customer c on o.customer_id = c.id
where o.id = 1
因为customer表和orders表的主键名都叫id,查询的时候如果写select c.*,o.* from orders
的话,就搞不清楚哪个id对应于哪张表,所以我们起了别名来将他们区分开来。
对应的实体类中,Orders类中必须有一个类型为Customer的属性customer。
对应的映射文件ordersMapper.xml为:
<?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-->
<mapper namespace="com.sxau.mybatis.mapper.OrdersMapper">
<resultMap id="ordersMap" type="orders">
<id property="id" column="oid"></id>
<result property="orderNumber" column="orderNumber"></result>
<result property="orderPrice" column="orderPrice"></result>
<!--javaType里存放的是类名而不是对象名-->
<association property="customer" javaType="Customer">
<id property="id" column="cid"></id>
<result property="name" column="name"></result>
<result property="age" column="age"></result>
</association>
</resultMap>
<select id="getById" resultMap="ordersMap">
select c.id cid,c.name,c.age,o.id oid,o.orderNumber,o.orderPrice
from orders o inner join customer c on o.customer_id = c.id
where o.id = #{id}
</select>
</mapper>
接下来我们来看一对多的连接。现在的需求是:根据客户的id查询这个客户相关联的所有订单信息。因为一个客户可能对应有多个订单,所以这是一对多的表关联查询。
sql语句:
select c.id cid,c.name,c.age,o.id oid,o.orderNumber,o.orderPrice
from customer c left join orders o on c.id = o.customer_id
where c.id = 1
这里如果使用内连接inner join,那么当一个客户没有生成任何订单信息时我们什么也查不到,也就是说我们想根据客户的id来查询客户信息并且捎带地查询该客户名下的订单信息,结果有了客户的id后只因为该客户没有生成订单,就查询不到该客户,这显然是违背了我们的本意,我们希望当客户没有与之关联的订单时,根据客户的id可以查到客户的信息只不过他的订单列表为空。所以,我们放弃使用inner join而改用了left join。left join的意思是左外连接,用左外连接做表关联查询时,它会始终保留左表(即主表)的所有相关列的信息。这样一来,就不会因为某个客户没有生成订单就查不出来这个客户的信息。
对应的实体类中,Customer类中必须有一个类型为List<Orders>
的属性ordersList,用来存放该客户的订单对象。
对应的映射文件ordersMapper.xml为:
<?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-->
<!--左外连接,left join 左表里的内容会完全显示-->
<!--记住一个口诀,resultMap的type值永远是这个mapper的namespace下的东西-->
<!--在一方关联多方时要注意的点,1,left左外连接 2,两个表的id名字冲突时必须起别名区分开-->
<mapper namespace="com.sxau.mybatis.mapper.CustomerMapper">
<resultMap id="customerMap" type="customer">
<id property="id" column="cid"></id>
<result property="name" column="name"></result>
<result property="age" column="age"></result>
<!--对应多方的集合的绑定,使用collection标签-->
<collection property="ordersList" ofType="Orders">
<id property="id" column="oid"></id>
<result property="orderNumber" column="orderNumber"></result>
<result property="orderPrice" column="orderPrice"></result>
</collection>
</resultMap>
<select id="getById" resultMap="customerMap">
select c.id cid,c.name,c.age,o.id oid,o.orderNumber,o.orderPrice
from customer c left join orders o on c.id = o.customer_id
where c.id = #{id}
</select>
</mapper>
Spring MVC:
下午老师讲了SpringMVC框架的基本流程以及搭建的步骤。
SpringMVC运行的基本流程:
- 向服务器发送HTTP请求,请求被前端控制器 DispatcherServlet 捕获。
- DispatcherServlet 根据 -servlet.xml 中的配置对请求的URL进行解析,得到请求资源标识符(URI)。 然后根据该URI,调用 HandlerMapping 获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以 HandlerExecutionChain 对象的形式返回。
- DispatcherServlet 根据获得的Handler,选择一个合适的 HandlerAdapter。
- 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。
数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等。
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。 - Handler(Controller)执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象
- 根据返回的ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet。
- ViewResolver 结合Model和View,来渲染视图。
- 视图负责将渲染结果返回给客户端
入门级SpringMVC框架搭建:
导入jar包:
编写配置文件web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--字符编码过滤器,防止中文乱码,这个过滤器必须放在所有内容的开始,否则不起作用-->
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--springmvc框架使用的是servlet进行注册-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
编写配置文件springmvc.xml:
<!--注册srpingmvc框架-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<!--指定注解扫描的根包-->
<context:component-scan base-package="com.oracle.demo.controller"></context:component-scan>
<!--视图解析器-->
<bean id = "ResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name = "prefix" value = "/"></property>
<property name = "suffix" value=".jsp"></property>
</bean>
</beans>
接下来介绍SpringMVC提交数据的4种方式(常见的):
- 第一种:散提(分散提交)
这种方式一般情况下要提交的数据不是很多,而且数据绑定时名字必须一致。
<%--${pageContext.request.contextPath}表示绝对路径的方式--%>
<form action="${pageContext.request.contextPath}/admin/one.action" method="post">
<p>姓名:<input name = "stuname"></p>
<p>密码:<input type="password" name = "stupwd"></p>
<p>年龄:<input type = "text" name="stuage"></p>
<p><input type="submit" value="提交"><input type="reset" value = "重置"></p>
</form>
@RequestMapping("/one")
public String one(String stuname,String stupwd,Integer stuage){
System.out.println(stuname+"-----"+stupwd+"---------"+(stuage+100));
return "main";
}
- 第二种:封装为一个对象
这种方式的优点是减少了代码的冗余且不容易出错,但前提是得事先创建好一个对应的java实体类。
<form action="${pageContext.request.contextPath}/admin/two.action" method="post">
<p>姓名:<input name = "stuname"></p>
<p>密码:<input type="password" name = "stupwd"></p>
<p>年龄:<input type = "text" name="stuage"></p>
<p><input type="submit" value="提交"><input type="reset" value = "重置"></p>
</form>
@RequestMapping("/two")
public String two(Student stu){
System.out.println(stu.getStuname()+"-----"+stu.getStupwd()+"---------"+(stu.getStuage()+100));
return "main";
}
- 第三种:@RequestParam注解方式
这种方式的好处在于进行数据绑定时可以定义别名。
<a href="${pageContext.request.contextPath}
/admin/three.action?name=王丽&age=12">第三种数据提交方式</a>
@RequestMapping("/three")
public String three(@RequestParam("name") String stuname,@RequestParam("age") int stuage){
System.out.println(stuname+"-----------"+(stuage+100));
return "main";
}
- 第四种:使用HttpServletRequest
这也是最原始的方式,它的缺点是数据的提取,类型转换都需要我们手动完成,优点是HttpServletRequest不局限于可以取数据,还可以调用其他方法完成各种功能。
<form action="${pageContext.request.contextPath}/admin/four.action" method="post">
<p>姓名:<input name = "stuname"></p>
<p>密码:<input type="password" name = "stupwd"></p>
<p>年龄:<input type = "text" name="stuage"></p>
<p><input type="submit" value="提交"><input type="reset" value = "重置"></p>
</form>
@RequestMapping("/four")
public String four(HttpServletRequest request){
String name = request.getParameter("stuname");
String pwd = request.getParameter("stupwd");
int age =Integer.parseInt(request.getParameter("stuage"));
System.out.println(name+"-----"+pwd+"---------"+(age+100));
return "main";
}