1.连接数据库
1.1.配置mybatis-confi.xml
开启驼峰匹配
开启懒加载
按需加载设置为false
配置一些插件(分页,通用mapper..)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 开启驼峰匹配规则 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
<!-- 开启懒加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 按需加载设置为false -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql" />
<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
<property name="rowBoundsWithCount" value="true" />
</plugin>
<plugin interceptor="com.github.abel533.mapperhelper.MapperInterceptor">
<property name="IDENTITY" value="MYSQL" />
<property name="mappers" value="com.github.abel533.mapper.Mapper"/>
</plugin>
</plugins>
</configuration>
1.2.配置spring-mybatis的整合(spring-mybatis.xml),最关键的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置注解扫描包,它会扫描基本包和子包的所有类,会检测当前的类中是否含有spring注解(@Controller,@Service,@Respitory,@Component)
这些注解的功能一致,名字不同是为了区别类在mvc中属于那一层: @Controller:前端数据交互 @Service:业务逻辑层 @Respitory:dao层
@Component:不属于mvc层可以使用该注解 (开启了注解扫描自动开启注解功能) -->
<context:component-scan base-package="com.action"></context:component-scan>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- 定义数据源,destory-method销毁的回调方法 -->
<bean class="com.jolbox.bonecp.BoneCPDataSource" id="dataSource"
destroy-method="close">
<!-- 数据库地址 -->
<property name="jdbcUrl" value="${jdbc.url}"></property>
<!-- 驱动 -->
<property name="driverClass" value="${jdbc.driverClassName}"></property>
<!-- 账号 -->
<property name="user" value="${jdbc.username}"></property>
<!-- 数据库地址 -->
<property name="password" value="${jdbc.password}"></property>
<!-- 检查数据库连接池中空闲连接的时间间隔,单位是分,默认值:240分,如果要取消则设置为0 -->
<property name="idleConnectionTestPeriod" value="60"></property>
<!-- 连接池中未使用链接的最大存活时间,单位是分,默认是60分,如果永远存活设置为0 -->
<property name="idleMaxAge" value="30"></property>
<!-- 每个分区的最大连接数 -->
<!-- 判断依据:请求并发数 -->
<!-- <property name="maxConnectionPerPartition" value="100"></property>
每个分区最小连接数 <property name="minConnectionPerPartition" value="5"></property> -->
</bean>
<!-- 如果要使用mybatis就要定义sqlSessionFactory,在spring和mybatis整合包里 -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 配置要加载的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 配置要加载的mapper.xml映射文件路径,这里放在mapper.xml中 -->
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
<!-- 配置别名 -->
<property name="typeAliasesPackage" value="com.action.pojo"></property>
</bean>
<!-- 配置mapper的接口扫描包,会为我们动态创建mapper代理并注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 定义扫描的包名 -->
<property name="basePackage" value="com.action.dao"></property>
</bean>
<!-- 配置事务管理器 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!-- 往事务管理器中注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置开启事务扫描transcation功能,并对含有注解的方法或类进行事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 定义事务策略,增强通知 -->
<tx:advice transaction-manager="transactionManager" id="txAdvice">
<tx:attributes>
<tx:method name="query*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- aop切面配置 -->
<aop:config>
<!-- *返回类型 *类 *方法 ..参数不限 -->
<aop:pointcut expression="execution(* com.action.service.*.*(..))" id="mypoint"/>
<!-- 将上述定义好的事务处理策略应用到上述切入点 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
</aop:config>
</beans>
2.springmvc的配置(转换器,静态资源加载)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--处理静态资源 -->
<mvc:default-servlet-handler />
<!-- 加载推荐使用的驱动 ,不用配置HandlerMapping和HandlerAdaptaher
配置格式转换器
-->
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="dataConverter"/>
</set>
</property>
</bean>
<!-- 自定义时间转换器,string>>date -->
<bean id="dataConverter" class="com.action.web.converter.DateConverter">
<property name="datePattern" value="yyyy-MM-dd"></property>
</bean>
<!-- 配置controller注解扫描 -->
<context:component-scan base-package="com.action.web.controller"></context:component-scan>
<!-- HandlerMapping和HandlerAdaptaher在服务被部署时就已经被创建 -->
<!-- 配置视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图解析路径 -->
<!-- prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" -->
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
3.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置spring容器初始化要加载的xml文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>
<!-- ContextLoaderListener:上下文监听器,当应用被部署到tomcat上时,就会产生上下文,那么监听器就能 监听到这一动作,监听器监听到这一动作后就会根据
context-param里面配置的xml地址创建spring容器, 也就是说,spring在应用部署到内存中之后就会初始化容器,并且只创建一次 -->
<!-- spring的ApplicationContext载入 -->
<listener>
<!-- 配置spring容器入口 -->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置过滤器 乱码问题处理:1.在web.xml文件中配置过滤器(post方式解决) 2.在tomcat的server.xml文件中的contoter节点下进行配置(get方式提交解决) -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<!-- 配置编码格式为utf-8 -->
<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>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置springmvc核心控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-servlet.xml</param-value>
</init-param>
<!-- 设置初始化优先级,数字越小越高,会在部署到tomcat时就被初始化创建 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置springmvc入口 -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
附懒加载的示例:
<!-- 懒加载开始测试,第一步在全局配置文件中使用setting标签开启,然后设置按需加载为false -->
<!-- 首先只查询报销单信息 -->
<resultMap type="Expense" id="lazyQuery" autoMapping="true">
<id column="userId" property="userId" />
<!-- 为什么不能开启自动匹配?就是因为如果不需要查询用户信息的话是没有user信息的,这个时候userId就是expens eId传入的用户id -->
<association property="user" select="query2" column="expenseId"></association>
</resultMap>
<select id="query2" resultType="User">select * from t_user where userId=#{userId}</select>
<select id="queryLazyExpenseUserById" resultMap="lazyQuery">
select * from t_expense where expenseId=#{expenseId}
</select>
Test:
package com.action.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
import com.action.mapper.ExpenseMapper;
import com.action.pojo.Expense;
import com.action.pojo.User;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
public class ExpenseUserTest {
private static SqlSession session;
private static ExpenseMapper mapper;
@BeforeClass
public static void init(){
try {
//获取全局配置文件
String path="mybatis-config.xml";
//获得流对象
InputStream in=Resources.getResourceAsStream(path);
//创建工厂对象
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
//创建session对象
session=factory.openSession();
//创建mapper代理对象
mapper=session.getMapper(ExpenseMapper.class);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Test
public void test(){
Expense e=mapper.queryLazyExpenseUserById(1);
System.out.println(e.toString());
User u=e.getUser();
System.out.println(u.toString());
}
}
readme:
缓存:先在作用域中进行查询,如果有,返回,如果没有数据再进数据库中找
一级缓存的作用域是session,默认开启,不能关闭
二级缓存的作用域是namespace,全局开关是开启的,局部的需要在相应的mapper.xml文件中通过标签打开
缓存当遇到增删改操作时会自动清除,查询不会,手动清除session.clearCache()方法清除
动态sql语句:#{}防止sql注入
条件语句的作用很大where,set,choose,foreach用于传递的参数是数组和集合的情况(权限控制)
还有resultMap的继承,遇到多对多的情况如何定义结果集类型
分页查询:导入pagehelper包和它的依赖包jsplparser包,使用plugins标签进行配置
注意:首先要开启分页功能,再将返回的list集合传到PageInfo类中变成一个分页类进行操作
sql程序片段:对重复使用的sql语句使用sql标签进行封装,再用include标签取出进行拼接
第二种方法就是将重复使用的代码片段放在xml文件中并配置进全局文件,使用就是名称空间+.sql的id
懒加载(按需加载):第一步:在全局配置文件中开启功能并设置按需加载为false,
第二步:在对应的mapper中自定义mapper类型
分页的controller和jsp:
/**
* 分页查询
* @param pageNum 当前页
* @param pageSize 页面大小
* @return
*/
@RequestMapping("/queryUsers")
public ModelAndView queryUsersByPlugins(Integer pageNum){
int pageSize=3;
ModelAndView model=new ModelAndView();
System.out.println("传入过来的pageNum是:"+pageNum);
if(pageNum==null){
pageNum=1;
}
//开启分页功能
PageHelper.startPage(pageNum,pageSize);
//紧跟着的第一个select方法会被分页
List<User> users=userService.queryUsersByPage(pageNum);
PageInfo<User> info=new PageInfo<User>(users);
model.addObject("users", users);
model.addObject("info", info);
model.setViewName("showUsers");
return model;
}
jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="resource/css/bootstrap.css">
<script type="text/javascript" src="resource/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="resource/js/bootstrap.min.js"></script>
</head>
<body>
<div class="cntainer">
<div class="row">
<div class="col-md-12" align="center">
<h1>人员列表</h1>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-honver">
<tr>
<th>用户编号</th>
<th>用户姓名</th>
<th>用户性别</th>
<th>用户年龄</th>
<th>用户电话</th>
<th>用户账号</th>
<th>用户工资</th>
<th>用户角色</th>
</tr>
<c:forEach items="${users}" var="u">
<tr>
<td>${u.userId}</td>
<td>${u.userName}</td>
<td>${u.userSex}</td>
<td>${u.userAge}</td>
<td>${u.userPhone}</td>
<td>${u.userAccount}</td>
<td>${u.userSalary}</td>
<td>${u.userRole}</td>
<td><button class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-pencil"></span>增加
</button></td>
<td><button class="btn btn-warning btn-sm">
<span class="glyphicon glyphicon-trash"></span>删除
</button></td>
</tr>
</c:forEach>
</table>
<!-- 分页 -->
<div class="message">
共<i class="blue">${info.total}</i>条记录,当前显示第 <i
class="blue">${info.pageNum}/${info.pages}</i> 页
</div>
<div style="text-align: center;">
<ul class="pagination">
<c:if test="${!info.isFirstPage}">
<li><a
href="queryUsers?pageNum=${info.firstPage}">首页</a></li>
<li><a
href="queryUsers?pageNum=${info.pageNum-1}">上一页</a></li>
</c:if>
<!-- 页码 -->
<c:forEach items="${info.navigatepageNums}"
var="navigatepageNum">
<c:if test="${navigatepageNum==info.pageNum}">
<li class="active"><a
href="javascript:(0);">${navigatepageNum}</a></li>
</c:if>
<c:if test="${navigatepageNum!=info.pageNum}">
<li><a
href="queryUsers?pageNum=${navigatepageNum}">${navigatepageNum}</a></li>
</c:if>
</c:forEach>
<c:if test="${!info.isLastPage}">
<li><a
href="queryUsers?pageNum=${info.pageNum+1}">下一页</a></li>
<li><a
href="queryUsers?pageNum=${info.lastPage}">最后一页</a></li>
</c:if>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>
时间类型转换的jsp:生日:<fmt:formatDate value="${user.birthday }" pattern="yyyy年MM月dd日"/>
DateConverter.java:
package com.action.web.converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
/**
* 将字符串转化成日期
* @author Administrator
*
*/
public class DateConverter implements Converter<String, Date>{
private String datePattern;
public void setDatePattern(String datePattern) {
this.datePattern = datePattern;
}
@Override
public Date convert(String s) {
// TODO Auto-generated method stub
SimpleDateFormat sf = new SimpleDateFormat(this.datePattern);
try {
Date d=sf.parse(s);
return d;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}