spring实战(仅仅是本人的学习笔记,可能会有错误,大家见谅)
简介
1.spring是什么?
2. spring优势?
3. spring体系结构
Spring快速入门
开发步骤
- 导入坐标
- 创建bean
- 创建applicationContext.xml
- 在配置文件中进行配置
- 创建ApplicationContext对象getBean
Spring配置文件的配置
用于配置对象交由Spring来创建
默认情况下它调用的类中的无参构造函数,如果没有无参构造函数则不能创建成功
基本属性:
id:唯一标识
class:Bean的全限定名称
Bean标签范围配置
scope:值对象的作用范围
取值范围:
singleton:默认的,单例的
prototype:多里的
request:web项目中,Spring创建一个Bean对象,将对象存入request对象
session: 将对象存入session域中
global session:Web项目中,应用在portlrt环境中,如果没有portlet环境那么globalSession 相当于session
Bean生命周期设置
Bean实例化的三种方式
- 无参构造
- 工厂静态方法
- 工厂实例化方法实例化
依赖注入
如何将UserDao注入到UserServce?
Set方法
例如:
简单方式:p命名空间
构造方法
例如:
bean容器可以注入集合,对象和普通的值
<bean id="userDao" class="com.itheima.Impl.UserDaoImpl">
<property name="list">
<list>
<value>"aaa"</value>
<value>"bbb"</value>
<value>"ccc"</value>
</list>
</property>
<property name="map">
<map>
<entry key="1" value-ref="user1"/>
</map>
</property>
<property name="properties">
<props>
<prop key="1">ppp</prop>
<prop key="2">ppp</prop>
<prop key="3">ppp</prop>
</props>
</property>
</bean>
引用其他配置文件 分模块开发
代码:
<import resource="applicationContext-xxx.xml"/>
Spring相关API
ApplicationContext的实现类
getBean()方法的使用:
id可以
写类名也可以
Spring配置数据源(连接池的作用)
数据源(连接池) 的作用:
- 提高程序的性能
- 实现实例化数据源,初始化部分连接资源
- 使用连接资源时从数据源中获取
- 使用完毕后将连接子渊归还给数据源
常见数据源:DBCP,C3P00,BoneCP,Druid等
数据源开发步骤:
- 导入数据源的坐标和数据可驱动坐标
- 创建数据源对象
- 设置数据源的基本连接数据
- 使用数据子渊获去连接资源和规划资源
两种获取数据源的方式:
public void test2() throws Exception {
DruidDataSource dataSource=new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8");
dataSource.setPassword("123123");
dataSource.setUsername("root");
DruidPooledConnection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
@Test
//测试cp30数据源
public void test1() throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8";
dataSource.setJdbcUrl(url);
dataSource.setUser("root");
dataSource.setPassword("123123");
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
通过properties获取数据源:
//将必要的数据写在properties中
jdbc.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=123123
//测试cp30数据源(加载properties版本)
public void test3() throws Exception {
ResourceBundle rb=ResourceBundle.getBundle("jdbc");
String driver=rb.getString("jdbc.driver");
String username=rb.getString("jdbc.username");
String password=rb.getString("jdbc.password");
String url=rb.getString("jdbc.url");
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setPassword(password);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setDriverClass(driver);
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
借助Spring配置数据源
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"/>
<property name="password" value="123123"/>
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
</bean>
Spring加载Property配置文件
核心:
Spring注解开发
Spring是轻代码重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
Spring原始注解
主要是用于替代的配置
注意:使用注解的时候要在bean中配置组件扫描
通过@Value注入普通数据类型
@Vulue(${} )注入 properties中的数据
@Scope 设置到底让你产生几个Bean
Spring新注解
原始注解无法解决的事情:
SpringJunit 测试
集成步骤
Spring集成web环境
通过设置监听器获取spring容器文件
- 编写监听类(实现 ServletContextListenser接口)
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//将想要放进容器中的东西创建出来
ApplicationContext app=new ClassPathXmlApplicationContext("SpringConfiguration.xml");
//新建一个serclet容器
ServletContext servletContext =servletContextEvent.getServletContext();
//将app放入接口中
servletContext.setAttribute("app",app);
System.out.println("监听器实现创建过了");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
- 在web文件中放入监听器映射
<listener>
<listener-class>com.itheima.listener.ContextLoaderListener</listener-class>
</listener>
- 在web层取出这个文件
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取这个容器
ServletContext servletContext = req.getServletContext();
//获取容器中的东西
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
//实现
UserService userService = app.getBean(UserService.class);
userService.save();
}
}
在web中设置全局变量
- 在web文件中设置全局参数
<!--web全局配置参数-->
<context-param>
<param-name>springConfiguration</param-name>
<param-value>SpringConfiguration.xml</param-value>
</context-param>
- 通过应用上下文获取设置在web中设置的全局参数
ServletContext servletContext = req.getServletContext();
//读取web中的全局变量
String springConfiguration = servletContext.getInitParameter("springConfiguration");
通过工具类获取上下文应用的值
好处:以为ServletContext 的attribute的值是耦合死的,不方便编程,所以设计工具类来方便编程将想要获取的放在上下文应用中
- 先存入
ApplicationContext app=new ClassPathXmlApplicationContext("SpringConfiguration.xml");
//新建一个serclet容器
ServletContext servletContext =servletContextEvent.getServletContext();
//将app放入接口中
servletContext.setAttribute("app",app);
System.out.println("监听器实现创建过了");
- 编写工具类
public class WebApplicationContext {
public static ApplicationContext getApplication(ServletContext servletContext){
return (ApplicationContext) servletContext.getAttribute("app");
}
}
- 通过工具类获取到这个值
ApplicationContext app= WebApplicationContext.getApplication(servletContext);
对于上述的这个工具类,Spring提供了一个包装类供使用
SpringMVC简介
开发过程
- 导入SpringMVC坐标
- 配置SpringMVC核心控制器和DispathServlet
- 创建Controller类和视图页面
- 使用注解配置Controller类汇总业务方法映射地址
- 配置SpringMVC核心文件spring-mvc.xml
- 客户端发起测试
Spring访问过程:
开发步骤:
- 导入springmvc的坐标
- 配置sprigmvc核心控制器DispathServlet
- 创建Controller类和视图页面
- 使用注解配置Controller类中业务方法的映厍地址
- 配置SpringMVC核心文件spring-mvc.xml
- 客户端发起请求测试
SpringMvc的组件解析
执行流程
注解解析:
@RequestMapping
作用:用于建立请求URL和处理方法之间的对应关系
位置:
类上:请求URL的第一集访问目录。此处不写的话就相当于应用 的根目录
方法上:请求URL的第二集目录,与类上的使用@RequestMapping标注的以及目录一起组成访问虚拟路径
属性:
注解解析:
xml文件的配置
- 内部资源视图解析器
相关组件:
前段控制器:DispatcherServlet
处理映射器:HandlerMapping
处理适配器:HandlerAdapter
处理器:Handler
视图解析器:View Resolver
视图:View
注解和配置:
请求映射器:@RequestMapping
视图解析器配置:
REDIRECT_URL_PREFIX=“redirect:”
FORWARD_URL_PREFIX=“forward:”
prefix=
suffix=
SpringMVC的数据响应:
(1)页面跳转
直接返回字符串
通过ModelAndView对象返回
(2)回写数据
直接返回字符串
返回对象或集合
页面跳转:
1.返回字符串的形式:
2.返回ModelAndeViewer
以下5中方式均可以:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/quick5")
public String save5(HttpServletRequest servletRequest){
servletRequest.setAttribute("username","张强");
return "success";
}
@RequestMapping("/quick4")
//modelView对象spring框架会自动注入创建
public String save4(Model model){
model.addAttribute("username","博学谷");
return "success";
}
@RequestMapping("/quick3")
//modelView对象spring框架会自动注入创建
public ModelAndView save3(ModelAndView modelAndView){
modelAndView.addObject("username","itheima");
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping("/quick2")
public ModelAndView save2(){
//model:封装数据
//view:展示数据
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("username","itheima");
//设置model名称
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping("/quick")
public String save(){
System.out.println("到达Controller层");
return "success";
}
}
回写数据
- 直接返回字符
Web基础阶段,客户端访问服务器端,如果想直接返回写字符串作为响应体返回的话,只需要使用response.getWriter().print(“Hello word”)即可,那么在Controller中想直接回写字符串该怎么样呢?
方法1. 通过response方法进行书写
public void save6(HttpServletResponse response) throws IOException {
response.getWriter().println("zq");
}
方法2.直接返回字符串,但是注意要对方法进行SpringBody的注释,告知Springmvc框架,不进行视图调准,直接进行数据响应。
@ResponseBody
public String save5() throws IOException {
return "ZQ";
}
将对象转为joson格式返回到页面上
@RequestMapping("/quick8")
//告诉服务器,我返回的是字符串,不是个View
@ResponseBody
public String save8() throws IOException {
User user=new User();
user.setUsername("zq");
user.setAge(18);
//使用ObjectMapper类,需要配置依赖
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(user);
return s;
}
//objectMapper的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
- 返回数据或集合
配置xml文件,直接将对象转为json传过去
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
配置xml文件比较麻烦,所以 可以通过配置注解来解决上面的事情,但是别忘记加入网址。
SpringMvc获得请求参数
客户端请求参数的格式是:name=vlaue&name=value
服务端要获得请求参数,优势还需要进行数据的封装,SpringMVC可以接收如下啊类型的参数
- 基本类型参数
- POJO类型参数
- 数组类型参数
- 集合类型参数
获得基本类型参数
Controller中的业务方法的参数名要与请求参数的name一致,参数会自动映射匹配
获得POJO类型参数
Controller中的业务方法的POJO参数名要与请求参数的name一致,参数会自动映射匹配
获得数组类型的参数
Controller中的业务方法数组名称与请求参数的name一致
封装集合类型的参数
获得集合参数时,要将集合参数包装到一个对象中才可以,但是在对象集合前加入@RequestBody就可以直接进行获取。
请求乱码问题的解决
在web.xml配置全局过滤器即可
<!-- 配置资源过滤器解决乱码问题-->
<filter>
<filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@RequestParam注解
将参数绑定,将请求的不是参数列表中对应的值得时候可以进行过参数的绑定,从而导致仍然能够打印这和名字。
获取Restful风格的参数
通过@PathVariable注解记性占位符的匹配获取工作
自定义类型装换器
springmvc已经提供了一些蟾宫的类型转换器,例如将客户的字符串转为int
但是不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自定义转换器。
步骤:
- 自定义转换器实现Converter接口
- 在配置文件中声明转换器
- 在中引用转换器
获得Servlet相关的API
获取请求头
文件上传
单文件上传:
1.文件上传客户端三要素
表单项type=“file” 表单的提交方式是post 表单的enctype属性是多部分呢表单形式,即enctype=“multipart/form-data”
2.文件上传原理
单文件上传实现:
3.注意,这里的名字要和jsp中名字一一致
多文件上传:
只需要在jsp中多准备一个控件,然后在Controller层中设置一个数组,进行循环操作。
JdbcTemplate
具体代码demo如下:
- 导入坐标,这里面有一个注意事项,mysq-connector-java的版本要和mysql对应,不对应会导致连接出错的情况。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
- 创建数据库对应的实体类,类型和名字要对应上
public class Account {
private double money;
private String name;
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 创建jdbcTemplate对象,并且执行数据操作
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8");
dataSource.setUser("root");
dataSource.setPassword("123123");
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
int row = jdbcTemplate.update("insert into account1 values(?,?)", "zs", 18);
System.out.println(row);
可以通过配置xml文件来实现JdbcTempplate的创建和数据库的连接
- 新建jdbc.properties文件 new file
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.password=123123
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
jdbc.user=root
- 配合xml文件
<!-- 配置ComboPooledDataSource-->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="password" value="${jdbc.password}"/>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
<property name="user" value="${jdbc.user}"/>
</bean>
<!-- 配置jdbcTemplate-->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="comboPooledDataSource"/>
</bean>
- 调用
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jdbcTemplate = app.getBean(JdbcTemplate.class);
int row = jdbcTemplate.update("insert into account1 values (?,?)", "ls", 188);
System.out.println(row);
增删改查模板
@Test
//查数量
public void query(){
Long aLong = jdbcTemplate.queryForObject("select count(*) from account1", Long.class);
System.out.println(aLong);
}
@Test
public void queryOne(){
//查一个
Account account = jdbcTemplate.queryForObject("select * from account1 where name =?", new BeanPropertyRowMapper<Account>(Account.class), "zs");
System.out.println(account);
}
@Test
//查全部
public void queryAll(){
List<Account> accounts = jdbcTemplate.query("select * from account1", new BeanPropertyRowMapper<Account>(Account.class));
System.out.println(accounts);
}
@Test
public void delete(){
//删除
jdbcTemplate.update("delete from account1 where name=?","ls");
}
@Test
public void update(){
//更新
jdbcTemplate.update("update account1 set money=99999 where name=?","zs");
}
@Test
public void insert(){
//插入
jdbcTemplate.update("insert into account1 values(?,?)","ls",1565651);
}
SpringMVC拦截器
作用:
过滤器和拦截器的区别:
快速入门:
1.
public class Myinterceptor1 implements HandlerInterceptor {
//在目标方法执行之前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
//在目标方法执行之后,视图对象返回之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
//在整个流程都执行完毕之后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
<!-- 配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 对那些资源进行拦截-->
<mvc:mapping path="/**"/>
<bean class="com.itheima.interceptor.Myinterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
多个拦截器的执行的先后顺序就是看谁在上谁在下
拦截方法说明
SpringMVC异常处理机制
异常处理思路:
异常处理的两种方式:
- 使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver
- 使用Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理接口
1.使用MVC异常处理器2. 自定义异常处理器
步骤:
public class MyExceptionResolver implements HandlerExceptionResolver {
/*
关键参数Exception 报异常的异常返回对象,跳转的错误视图的信息
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView modelAndView=new ModelAndView();
if(ex instanceof MyException){
modelAndView.addObject("info","自定义的异常");
}else if(ex instanceof ClassCastException){
modelAndView.addObject("info","类型转换异常");
}
modelAndView.setViewName("error");
return modelAndView;
}
}
<bean class="com.itheima.resolver.MyExceptionResolver"/>
SpringAop
什么是aop?
作用及其优势
底层实现:
动态代理技术:
- jdk
public class ProxyTset {
public static void main(String[] args) {
//目标对象
final Target target = new Target();
//增强对象
final Advice advice = new Advice();
TargetInterface targetInterface=(TargetInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
advice.before();
Object invoke = method.invoke(target, args);
advice.after();
return invoke;
}
}
);
targetInterface.save();
}
}
- cglib的动态代理
public class ProxyTset {
public static void main(String[] args) {
//目标对象
final Target target = new Target();
//增强对象
final Advice advice = new Advice();
//返回值就是动态生成的代理技术
//1.创建增强器
Enhancer enhancer = new Enhancer();
//2.设置父类(目标 )
enhancer.setSuperclass(Target.class);
//3.设置回调
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//前置增强
advice.before();
method.invoke(target,args);
advice.after();
return null;
}
});
//4.创建代理对象
Target proxy= (Target) enhancer.create();
proxy.save();
}
}
相关概念:
解释:
连接点被拦截到的方法就是连接点,切入点就是拦截到并且真的被增强的方法叫切入点
切面:切点加通知
注意事项:
- 需要编写的内容:
技术实现的内容:
aop底层使用哪种代理方式:
知识要点:
基于XML的aop开发快速入门
快速入门
核心就在于xml文文件的配置
<!--配置目标对对象-->
<bean id="target" class="com.itheima.proxy.aop.Target"/>
<!-- 配置通知-->
<bean id="myAspect" class="com.itheima.proxy.aop.MyAspect"/>
<!-- 配置织入:告诉spring框架,那些方法(切点)需要增强(前置,后置)-->
<aop:config>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut="execution(public void com.itheima.proxy.aop.Target.save())"/>
</aop:aspect>
</aop:config>
切点表达式的写法
语法:
例子解释:
- 指定包下面方法和类
- 指定方法下的没有返回值的
- 包下的任意类任意方法
- aop包以及子包都能增强
- 都任意
通知的类
切点表达式抽取
<aop:config>
<aop:aspect ref="myAspect">
<aop:pointcut id="pointcut1" expression="execution(* com.itheima.proxy.aop.*.* (..))"/>
<aop:around method="around" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
基于注解的aop开发快速入门
步骤:
- 注入目标类
@Component("target")
public class Target implements TargetInterface {
public void save() {
System.out.println("run save*********");
}
}
- 配置切面
类名的上面
@Component("myAspect")
@Aspect
public class MyAspect {
对应的增强方法
@Before("execution(* com.itheima.proxy.anno.*.* (..))")
public void before(){
System.out.println("前置增强************");
}
3.在xml文件中配置目标类和自动代理
<context:component-scan base-package="com.itheima.proxy.anno"/>
<!-- 自动代理-->
<aop:aspectj-autoproxy/>
注解配置的AOP 类型
事务控制
编程式事务控制
接只定义行为
事务定义对象:定义信息对象
事务隔离级别
事务传播行为
被动的封装事务的信息
声明式事务控制
什么是声明式事务控制:
<!-- 配置平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/>
<!-- 通知事务增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 设置事务的属性信息-->
<tx:attributes>
<!-- 这里面可以增加多个方法-->
<tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" timeout="-1" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- AOP事务的织入-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl.*.*(..))"/>
</aop:config>
声明式事务控制的要点:
- 平台事务配置器
- 事务通知的配置
- 事务aop织入的配置
基于注解的声明式控制
MyBatis
原始的jdbc连接数据库
插入数据
原始jdbc操作分析
什么是mybatis
快速入门
步骤:
4.
<mapper namespace="userMapper">
<select id="findAll" resultType="com.itheima.domain.User">
select * from user
</select>
</mapper>
<!-- 配置数据源环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="123123"/>
</dataSource>
</environment>
</environments>
<!--导入userMapper资源-->
<mappers>
<mapper resource="com/itheima/mapper/UserMapper.xml"/>
</mappers>
</configuration>
public class myBatisTest {
@Test
public void test1() throws IOException {
//通过Resource获取资源文件
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapperConfig.xml”);
//新建Session工厂
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获取Session对话
SqlSession sqlSession = build.openSession();
//调用命名空间,进行查询
User user = new User();
user.setId(7);
user.setUsername(“lilian”);
user.setPassword(“123123”);
sqlSession.insert(“userMapper.insert”,user);
List<User> userList = sqlSession.selectList("userMapper.findAll");
System.out.println(userList);
//释放资源
sqlSession.close();
}
}
映射文件概述
增删改查操作
插入:
<!-- 插入操作-->
<insert id="insert" parameterType="com.itheima.domain.User">
insert into user values (#{id},#{username},#{password})
</insert>
<!-- 修改数据-->
<update id="update" parameterType="com.itheima.domain.User">
update user set username=#{username},password=#{password} where id=#{id}
</update>
<!-- 删除数据-->
<delete id="delete" parameterType="com.itheima.domain.User">
delete from user where id=#{id}
</delete>
知识小结:
增删改查映射配置与API:
MyBatis核心配置文件层级关系
environment标签
数据库环境的配置,支持多环境配置
mapper
作用是用于加载映射的,加载方式有一下几种:
properties
实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties。
typeAliases
类型别名是为Jva类型设置一个短的名字,原来的类型名称配置如下:
已经将常用的类型定义好了别名
知识小结:
MyBatis响应的API
SqlSession工厂构造器SqlSessionFactoryBuilder
常用API:SqlSessionFactory build(InputStream inputStream)
MyBatis的Dao层实现
代理开发方式:
MyBatis映射文件深入
- 动态sql语句描述
动态SQL if
动态SQL foreach
Sql片段抽取
总结:
MyBatis 核心配置文件深入
typeHandlers标签
重新定义类型转换器
开发步骤
1.
public class DateTypeHandler extends BaseTypeHandler<Date> {
//将java类型转化成数据库中需要的类型
public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
long time = parameter.getTime();
ps.setLong(i,time);
}
//将数据库中的类型转换成java类型
//columnName是数据库中要转换的字段的名称
//rs查询的结果集
public Date getNullableResult(ResultSet rs, String columnName) throws SQLException {
//将获取到的数据转换成long类型
long aLong = rs.getLong(columnName);
//然后转换成date类型
Date date = new Date(aLong);
return date;
}
//将数据库中的类型转换成java类型
public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
long aLong = rs.getLong(columnIndex);
Date date = new Date(aLong);
return date;
}
//将数据库中的类型转换成java类型
public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
long aLong = cs.getLong(columnIndex);
Date date = new Date(aLong);
return date;
}
}
<!--自定义注册器-->
<typeHandlers>
<typeHandler handler="itheima.handler.DateTypeHandler" javaType="java.util.Date"/>
</typeHandlers>
plugins标签
- 在pom文件中导入坐标
<!-- mybatis pager -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.4</version>
</dependency>
- 配置核心文件中的插件
<!-- 配置plugins分页助手-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
3.在测试中编写测试的代码
PageHelper.startPage(1,2);
拓展:获取与分页相关的参数
MyBatis多表操作
多表查询中,将多表查询的结果和现实中的结果一一对应
一对一
<resultMap id="orderMap" type="order">
<!-- column是数据库中查询到的列,property是我们要封装进的实体-->
<result column="oid" property="id"/>
<result column="ordertime" property="ordertime"/>
<result column="total" property="total"/>
<result column="uid" property="user.id"/>
<result column="username" property="user.username"/>
<result column="password" property="user.password"/>
<result column="birthday" property="user.birthday"/>
</resultMap>
<!--这里结果要改成resultMap-->
<select id="findAll" resultMap="orderMap">
select *,o.id oid
from orders o inner join user u on u.id=o.uid
</select>
将查询到的关联表封装在另一个类中的另一种封住方式:
<resultMap id="orderMap" type="order">
<result column="oid" property="id"/>
<result column="ordertime" property="ordertime"/>
<result column="total" property="total"/>
<!-- property是order中的属性
javaType是实际的类
-->
<association property="user" javaType="user">
<result column="uid" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="password" property="password"/>
</association>
</resultMap>
一对多
<resultMap id="userMapper" type="user">
<result property="id" column="uid"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<collection property="orderList" ofType="order">
<result column="oid" property="id"/>
<result column="ordertime" property="ordertime"/>
<result column="total" property="total"/>
</collection>
</resultMap>
<select id="findAll" resultMap="userMapper">
SELECT *,o.id oid FROM orders o INNER JOIN USER u ON u.id=o.uid
</select>
多对多
总结:
MyBatis的注解开发
**一对多 **
SSM框架整合
原始方式整合
Spring整合Mybatis