文章目录
写在前面
以下内容是我在自学(小破站找的视频)ssm框架时记录的笔记,之前一直在电脑上保存,为了保存和分享现在把笔记整到csdn,如果有错误和不足的地方欢迎指正,暂时我只记录了这么多,日后我的知识储备多了也会不断补充和完善。
正文
一、SpringIOC(xml)
1.快速入门
①导入 Spring 开发的基本包坐标
在项目pom.xml文件中导入spring坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
②编写 Dao 接口和实现类
UserDao、UserDaoImpl。
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save running....");
}
}
③创建 Spring 核心配置文件
在resources目录下创建核心配置文件applicationContext.xml(名称任意,习惯性命名为applicationContext)。
④在 Spring 配置文件中配置 UserDaoImpl
其中id是唯一标识(任意名称),class为需要实例化bean的全限定名(包名.类名)。
<bean id="userDao" class="com.fbst.dao.impl.UserDaoImpl"></bean>
⑤使用 Spring 的 API 获得 Bean 实例
创建测试类UserDaoDemo,通过ApplicationContext对象的getBean()方法获得bean对象,从而调用对象中的方法。
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");//指定配置文件名
UserDao userDao = (UserDao) app.getBean("userDao");//通过<bean>标签中的id唯一标识获取指定的bean对象
userDao.save();
}
}
2.知识要点
①导入坐标
②创建Bean
③创建applicationContext.xml
④在配置文件中进行配置
⑤创建ApplicationContext对象getBean
3.配置文件
3.1Bean标签范围配置
<bean id="userDao" class="com.fbst.dao.impl.UserDaoImpl" scope=""></bean>
scope:指对象的作用范围,取值如下:
取值范围 | 说明 |
---|---|
singleton | 默认值,单例的 |
prototype | 多例的 |
request | WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中 |
session | WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中 |
global session | WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session |
1)当scope的取值为singleton时
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期:
对象创建:当应用加载,创建容器时,对象就被创建了
对象运行:只要容器在,对象一直活着
对象销毁:当应用卸载,销毁容器时,对象就被销毁了
2)当scope的取值为prototype时
Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,就一直活着
对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了
3.2Bean生命周期配置
在UserDaoImp添加以下两个方法:
public void init(){
System.out.println("初始化方法....");
}
public void destory(){
System.out.println("销毁方法....");
}
init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称
<bean id="userDao" class="com.fbst.dao.impl.UserDaoImpl"
init-method="init" destory-method="destory">
</bean>
3.3Bean实例化的三种方式
1.无参构造方法实例化
2.工厂静态方法实例化
3.工厂实例方法实例化
1) 使用无参构造方法实例化
它会根据默认无参构造方法来创建类对象,如果bean中没有默认无参构造函数,将会创建失败
<bean id="userDao" class="com.fbst.dao.impl.UserDaoImpl"/>
2) 工厂静态方法实例化
工厂的静态方法返回Bean实例
public class StaticFactory {
public static UserDao getUserDao(){
return new UserDaoImpl();
}
}
<bean id="userDao" class="com.fbst.factory.StaticFactory" factory-method="getUserDao" />
3) 工厂实例方法实例化
工厂的非静态方法返回Bean实例
public class DynamicFactory {
public UserDao getUserDao() {
return new UserDaoImpl();
}
}
<bean id="factoryBean" class="com.fbst.factory.DynamicFactory"/>
<bean id="userDao" factory-bean="factoryBean" factory-method="getUserDao"/>
3.4 Bean的依赖注入方式
1.构造方法
2.set方法
1)构造方法方式注入:
①创建有参构造
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save running....");
}
}
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl() {
}
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
②配置Spring容器调用有参构造时进行注入
<bean id="userDao" class="com.fbst.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.fbst.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
2)set方法方式注入:
方式1:
①创建 UserService,UserService 内部在调用 UserDao的save() 方法
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
②将 UserServiceImpl 的创建权交给 Spring
property标签中:
name属性值与UserServiceImpl中的setUserDao方法对应(setUserDao --> userDao)。
ref属性指定需要注入的对象id唯一表示。
<bean id="userDao" class="com.fbst.dao.impl.UserDaoImpl">
<bean id="userService" class="com.fbst.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
③从 Spring 容器中获得 UserService 进行操作
方式2:P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:
首先,需要引入P命名空间:
xmlns:p="http://www.springframework.org/schema/p"
其次,需要修改注入方式:
<bean id="userService" class="com.fbst.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
3.5 引入其他配置文件(分模块开发)
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载
<import resource="文件名.xml"/>
3.6 知识要点
bean标签
id属性:在容器中Bean实例的唯一标识,不允许重复
class属性:要实例化的Bean的全限定名
scope属性:Bean的作用范围,常用是Singleton(默认)和prototype
property标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
import标签:导入其他的Spring的分文件
4.Spring相关API
4.1ApplicationContext的实现类
1)ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件,推荐使用这种
2)FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
3)AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
4.2 getBean()方法使用
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。
当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService1 = (UserService) applicationContext.getBean("userService");
UserService userService2 = applicationContext.getBean(UserService.class);
4.3知识要点
Spring的重点API
ApplicationContext app = new ClasspathXmlApplicationContext("xml文件")
app.getBean("id")
app.getBean(Class)
二、Spring IOC(注解)
1.Spring原始注解
注解 | 说明 |
---|---|
@Component | 使用在类上用于实例化Bean |
@Controller | 使用在web层类上用于实例化Bean |
@Service | 使用在service层类上用于实例化Bean |
@Repository | 使用在dao层类上用于实例化Bean |
@Autowired | 使用在字段上用于根据类型依赖注入 |
@Qualifier | 结合@Autowired一起使用用于根据名称进行依赖注入 |
@Resource | 相当于@Autowired+@Qualifier,按照名称进行注入 |
@Value | 注入普通属性 |
@Scope | 标注Bean的作用范围 |
@PostConstruct | 使用在方法上标注该方法是Bean的初始化方法 |
@PreDestory | 使用在方法上标注该方法是Bean的销毁方法 |
2.Spring注解开发
首先创建UserDao、UserDaoImpl、UserServic、UserServicImpl
public interface UserDao {
public void save();
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save running...");
}
}
public interface UserService {
public void save();
}
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired //按照数据类型从Spring容器中进行匹配的
private UserDao userDao;
public void save() {
userDao.save();
}
}
其次分别在UserDaoImpl、UserServiceImpl、private UserDao userDao;上方添加@Repository(“userDao”)、@Service(“userService”)、@Autowired 等注解。
@Repository(“userDao”)
< bean id=“userDao” class=“com.fbst.dao.impl.UserDaoImpl”/>
@Service(“userService”)
< bean id=“userService” class=“com.fbst.service.impl.UserServiceImpl”/>
@Autowired
< property name=“userDao” ref=“userDao”/>
注意:使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。
<context:component-scan base-package="com.fbst"/>
代码测试:
public class UserController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = app.getBean(UserService.class);
userService.save();
}
}
3.Spring新注解
注解 | 说明 |
---|---|
@Configuration | 用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解 |
@ComponentScan | 用于指定Spring在初始化容器时要扫描的包。作用和在Spring的xml配置文件中的<context:component-scan base-package=“com.fbst”/>一样 |
@bean | 使用在方法上,标注将该方法的返回值存储到Spring容器中 |
@PropertySource | 用于加载properties文件中的配置 |
@Important | 用于导入其他配置类 |
创建核心配置类:
@Configuration
@ComponentScan("com.fbst")
public class SpringCofiguration {
}
注解说明:
注解 | 说明 |
---|---|
@Configuration | 标志该类是Spring的核心配置类,相当于一个ApplicationContext.xml文件 |
@ComponentScan(“com.fbst”) | 相当于<context:component-scan base-package=“com.fbst”/> |
@PropertySource(“classpath:jdbc.properties”) | 加载properties配置文件 |
@Import({DataSourceConfiguration.class}) | 导入其他副配置文件(DataSourceConfiguration)类 |
三、Spring集成Junit
开发步骤
①导入spring集成Junit的坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
②使用@Runwith注解替换原来的运行期
③使用@ContextConfiguration指定配置文件或配置类
④使用@Autowired注 入需要测试的对象
⑤创建测试方法进行测试
代码实现
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration(classes = {SpringCofiguration.class})
public class SpringJunitTest {
@Autowired
private UserService userService;
@Autowired
private DataSource dataSource;
@Test
public void test1() throws SQLException {
userService.save();
System.out.println(dataSource.getConnection());
}
}
四、Spring配置数据源
1.数据源的开发步骤
①导入数据源的坐标和数据库驱动坐标
②创建数据源对象
③设置数据源的基本连接数据
④使用数据源获取连接资源和归还连接资源
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
public class DataSourceTest {
@Test
//测试手动创建 c3p0 数据源(加载properties配置文件)
public void test3() throws Exception {
//读取配置文件
ResourceBundle rb = ResourceBundle.getBundle("jdbc");
String driver = rb.getString("jdbc.driver");
String url = rb.getString("jdbc.url");
String username = rb.getString("jdbc.username");
String password = rb.getString("jdbc.password");
//创建数据源对象 设置连接参数
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
@Test
//测试手动创建 druid 数据源
public void test2() throws Exception {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("root");
DruidPooledConnection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
@Test
//测试手动创建 c3p0 数据源
public void test1() throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser("root");
dataSource.setPassword("root");
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
}
jdbc.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
2.Spring配置
导入Spring坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
配置数据源:
其中class属性是使用的数据源的全限定名,name属性是指定数据源set方法名xxx(setXxx --> xxx)。
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
代码测试:
@Test
//测试Spring容器产生数据源对象
public void test4() throws Exception {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = app.getBean(DataSource.class);
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
3.抽取jdbc配置文件
applicationContext.xm加载jdbc.properties配置文件获得连接信息。
首先,需要引|入context命名空间和约束路径:
命名空间: xmIns:context=“http://www.springframework.org/schema/context”
约束路径: http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<!--加载外部的properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
五、Spring MVC
1.Spring集成web环境
首先,创建service层和dao层,接下来按着下面步骤进行操作。
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save running....");
}
}
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
①在pom.xml中导入spring-web坐标、Servlet相关坐标。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
②在web.xml中配置ContextLoaderListener监听器和全局初始化参数。
<!--配置监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--全局初始化参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
③创建web层,使用WebApplicationContextUtils获得应用上下文对象ApplicationContext。
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService userService = app.getBean(UserService.class);
userService.save();
}
}
2.Spring MVC快速入门
开发步骤:
①在pom.xml导入Spring、SpringMVC、Servlet和jsp的坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
②在web.xml配置SpringMVC的核心控制器
<!--配置springmvc前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--参数为正数时,表示服务器启动时,创建servlet对象-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
③创建Controller和业务方法
public class UserController {
public String save() {
System.out.println("Controller save running...");
return "success.jsp";
}
}
④创建视图页面Success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h>Success!</h1>
</body>
</html>
⑤使用注解配置Controller类中业务方法的映射地址
@Controller//把当前类放入Spring容器中
@RequestMapping("/user")//会和当前方法上的地址拼接在一起组成最终访问地址
public class UserController {
@RequestMapping(value = "/quick")//设置请求路径
public String save() {
System.out.println("Controller save running...");
return "success.jsp";//指定要跳转的视图界面
}
}
⑥配置SpringMVC核心文件 spring-mvc.xml
首先需要导入context命名空间。
xmlns:context="http://www.springframework.org/schema/context"
<!--在xsi:schemaLocation中添加-->
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
<!--Controller的组件扫描-->
<context:component-scan base-package="com.fbst.contorller"></context:component-scan>
在配置springmvc前端控制器时添加以下配置,告诉spring-mvc.xml文件位置。
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
⑦客户端发起请求测试
打开浏览器访问:localhost:8080/user/quick
结果:页面显示Success!
3.知识要点
①导入SpringMVC相关坐标
②配置SpringMVC核心控制器DispathcerServlet
③创建Controller类和视图页面
④使用注解配置Controller类中业务方法的映射地址
⑤配置SpringMVC核心文件 spring-mvc.xml
⑥客户端发起请求测试
六、Spring MVC视图解析器
在spring-mvc.xml中配置:
<!--配置内部资源视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--/jsp/success.jsp-->
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
现在刚才的测试代码可以优化为:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/quick")
public String save() {
System.out.println("Controller save running...");
return "success";
}
}
七、Spring AOP
1.基于XML的AOP开发
1.1快速入门
①导入 spring、AOP 相关坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency>
②创建目标接口和目标类(内部有切点)
public interface TargetInterface {
public void save();
}
public class Target implements TargetInterface {
public void save() {
System.out.println("save running.....");
}
}
③创建切面类(内部有增强方法)
public class MyAspect {
public void before(){
System.out.println("前置增强..........");
}
public void afterReturning(){
System.out.println("后置增强..........");
}
public void after(){
System.out.println("最终增强..........");
}
}
④将目标类和切面类的对象创建权交给 spring
<!--目标对象-->
<bean id="target" class="com.fbst.aop.Target"></bean>
<!--切面对象-->
<bean id="myAspect" class="com.fbst.aop.MyAspect"></bean>
⑤在 applicationContext.xml 中配置织入关系
首先需要引入aop命名空间
<!--引入aop命名空间-->
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
<!--配置织入:告诉spring框架 哪些方法(切点)需要进行哪些增强(前置、后置...)-->
<aop:config>
<!--声明切面-->
<aop:aspect ref="myAspect">
<!--切面:切点+通知-->
<aop:before method="before" pointcut="execution(public void com.fbst.aop.Target.save())"/>
</aop:aspect>
</aop:config>
⑥导入spring-text、junit依赖坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
测试代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.save();
}
}
1.2切点表达式的写法
表达式语法:
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
1.访问修饰符可以省略
2.返回值类型、包名、类名、方法名可以使用星号* 代表任意
3.包名与类名之间一个点 . 代表当前包下的类,两个点 … 表示当前包及其子包下的类
4.参数列表可以使用两个点 … 表示任意个数,任意类型的参数列表
例如:
execution(public void com.fbst.aop.Target.method())
execution(void com.fbst.aop.Target.*(…))
execution(* com.fbst.aop. * . * (…)) (最常用的)
execution(* com.fbst.aop… * . * (…))
execution(* * . . *. *(…))
1.3通知的类型
通知的配置语法:
<aop:通知类型 method=“切面类中方法名” pointcut=“切点表达式"></aop:通知类型 >
名称 | 标签 | 说明 |
---|---|---|
前置通知 | <aop:before > | 用于配置前置通知。指定增强的方法在切入点方法之前执行 |
后置通知 | <aop:after-returning > | 用于配置后置通知。指定增强的方法在切入点方法之后执行 |
环绕通知 | <aop:around > | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 |
异常抛出通知 | <aop:throwing > | 用于配置异常抛出通知。指定增强的方法在出现异常时执行 |
最终通知 | <aop:after > | 用于配置最终通知。无论增强方式执行是否有异常都会执行 |
1.4 切点表达式的抽取
当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替 pointcut 属性来引用抽取后的切点表达式。
<aop:config>
<!--抽取切点表达式-->
<aop:pointcut id="myPointcut" expression="execution(* com.fbst.aop.*.*(..))"></aop:pointcut>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
1.5知识要点
aop织入的配置
<aop:config>
<aop:aspect ref="切面类">
<aop:after method="通知方法名" pointcut="切点表达式"/>
<aop:after method="通知方法名" pointcut-ref="切点表达式对象引用(id)"/>
</aop:aspect>
</aop:config>
通知的类型:前置通知、后置通知、环绕通知、异常抛出通知、最终通知
切点表达式的写法:
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
2.基于注解的AOP开发
2.1快速入门
基于注解的aop开发步骤:
①创建目标接口和目标类(内部有切点)
public interface TargetInterface {
public void save();
}
public class Target implements TargetInterface {
public void save() {
System.out.println("save running.....");
}
}
②创建切面类(内部有增强方法)
public class MyAspect {
public void before(){
System.out.println("前置增强..........");
}
public void afterReturning(){
System.out.println("后置增强..........");
}
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前增强....");
Object proceed = pjp.proceed();//切点方法
System.out.println("环绕后增强....");
return proceed;
}
public void afterThrowing(){
System.out.println("异常抛出增强..........");
}
public void after(){
System.out.println("最终增强..........");
}
}
③将目标类和切面类的对象创建权交给 spring
@Component("target")
public class Target implements TargetInterface {
...
}
@Component("myAspect")
public class MyAspect {
...
}
④在切面类中使用注解配置织入关系
@Component("myAspect")
@Aspect //标注当前MyAspect是一个切面类
public class MyAspect {
//配置前置通知
//@Before("execution(* com.fbst.anno.*.*(..))")
public void before(){
System.out.println("前置增强..........");
}
public void afterReturning(){
System.out.println("后置增强..........");
}
//Proceeding JoinPoint: 正在执行的连接点===切点
//@Around("execution(* com.fbst.anno.*.*(..))")
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前增强....");
Object proceed = pjp.proceed();//切点方法
System.out.println("环绕后增强....");
return proceed;
}
public void afterThrowing(){
System.out.println("异常抛出增强..........");
}
//@After("execution(* com.fbst.anno.*.*(..))")
@After("MyAspect.pointcut()")
public void after(){
System.out.println("最终增强..........");
}
}
⑤在配置文件中开启组件扫描和 AOP 的自动代理(applicationContext-anno.xml)
<!--组件扫描-->
<context:component-scan base-package="com.fbst.anno"/>
<!--aop自动代理-->
<aop:aspectj-autoproxy/>
⑥测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-anno.xml")
public class AnnoTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.save();
}
}
2.2注解配置详解
注解通知的类型
通知的配置语法:@通知注解(切点表达式)
名称 | 注解 | 说明 |
---|---|---|
前置通知 | @Before | 用于配置前置通知。指定增强的方法在切入点方法之前执行 |
后置通知 | @AfterReturning | 用于配置后置通知。指定增强的方法在切入点方法之后执行 |
环绕通知 | @Around | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 |
异常抛出通知 | @AfterThrowing | 用于配置异常抛出通知。指定增强的方法在出现异常时执行 |
最终通知 | @After | 用于配置最终通知。无论增强方式执行是否有异常都会执行 |
切点表达式的抽取
同 xml 配置 aop 一样,我们可以将切点表达式抽取。抽取方式是在切面内定义方法,在该方法上使用@Pointcut注解定义切点表达式,然后在在增强注解中进行引用。具体如下:
@Component("myAspect")
@Aspectpublic class MyAspect {
@Before("MyAspect.myPoint()")
public void before(){
System.out.println("前置代码增强.....");
}
@Pointcut("execution(* com.fbst.aop.*.*(..))")
public void myPoint(){}
}
2.3知识要点
注解aop开发步骤:
①使用@Aspect标注切面类
②使用@通知注解标注通知方法
③在配置文件中配置aop自动代理<aop:aspectj-autoproxy/ >
3.基于XML的声明式事务控制
3.1.声明式事务控制的实现
①引入tx命名空间
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
②配置事务增强
<!--配置平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--通知 事务的增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--设置事务的属性信息的-->
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
③配置事务 AOP 织入
<!--配置事务的aop织入-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.fbst.service.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
④测试事务控制转账业务代码
配置数据源、jdbcTemplate、accountDao及accountService
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.fbst.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--目标对象 内部的方法就是切点-->
<bean id="accountService" class="com.fbst.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
创建web层、service层及dao层
public class Account {
private String name;
private double money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
public interface AccountDao {
public void out(String outMan, double money);
public void in(String inMan, double money);
}
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void out(String outMan, double money) {
jdbcTemplate.update("update account set money=money-? where name=?",money,outMan);
}
public void in(String inMan, double money) {
jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);
}
}
public interface AccountService {
public void transfer(String outMan,String inMan,double money);
}
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
int i = 1/0;//自定义异常用于测试
accountDao.in(inMan,money);
}
}
public class AccountController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = app.getBean(AccountService.class);
accountService.transfer("tom", "lucy", 500);
}
}
3.2切点方法的事务参数的配置
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--设置事务的属性信息的-->
<tx:attributes>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="save" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="findAll" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
其中,<tx:method > 代表切点方法的事务参数的配置
例如:
name:切点方法名称
isolation:事务的隔离级别
propogation:事务的传播行为
timeout:超时时间
read-only:是否只读
3.3知识要点
声明式事务控制的配置要点:
平台事务管理器配置
事务通知的配置
事务aop织入的配置
数据库表:
CREATE TABLE `account` (
`name` varchar(20) DEFAULT NULL,
`money` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
4.基于注解的声明式事务控制
4.1使用注解配置声明式事务控制
①修改AccountDaoImpl
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void out(String outMan, double money) {
jdbcTemplate.update("update account set money=money-? where name=?",money,outMan);
}
public void in(String inMan, double money) {
jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);
}
}
②修改AccountServiceImpl
@Service("accountService")
@Transactional(isolation = Isolation.REPEATABLE_READ)
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
int i = 1/0;//自定义异常用于测试
accountDao.in(inMan,money);
}
}
③修改applicationContext.xml 配置文件
<!--组件扫描-->
<context:component-scan base-package="com.fbst"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--事物的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
测试代码:
public class AccountController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = app.getBean(AccountService.class);
accountService.transfer("tom","lucy",500);
}
}
4.2注解配置声明式事务控制解析
①使用 @Transactional 在需要进行事务控制的类或是方法上修饰,注解可用的属性同 xml 配置方式,例如隔离级别、传播行为等。
②注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置。
③使用在方法上,不同的方法可以采用不同的事务参数配置。
④Xml配置文件中要开启事务的注解驱动<tx:annotation-driven />
4.3知识要点
注解声明式事务控制的配置要点
平台事务管理器配置(xml方式)
事务通知的配置(@Transactional注解配置)
事务注解驱动的配置 <tx:annotation-driven/ >
八、Mybatis
1.Mybatis快速入门
1.1添加MyBatis坐标和其他相关坐标
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
1.2创建user数据表
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`uname` varchar(50) DEFAULT NULL,
`passwd` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
1.3编写User实体类
public class User {
private int id;
private String uname;
private String passwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", uname='" + uname + '\'' +
", passwd='" + passwd + '\'' +
'}';
}
}
1.4编写映射文件UserMapper.xml
(在resources目录下创建com/fbst/mapper/UserMapper.xml)
先引入dtd约束头
<?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="userMapper">
<select id="findAll" resultType="com.fbst.domain.User">
select * from user
</select>
</mapper>
1.5编写核心文件SqlMapConfig.xml
同样先引入dtd约束头
<configuration>
<!--数据源环境-->
<environments default="developement">
<environment id="developement">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="com/fbst/mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
1.6编写测试代码
public class MyBatisTest {
@Test
//查询操作
public void test1() throws IOException {
//获得核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//获得session工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得session回话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行操作 参数:namespace+id
List<User> userList = sqlSession.selectList("userMapper.findAll");
//打印数据
System.out.println(userList);
//释放资源
sqlSession.close();
}
}
1.7知识小结
MyBatis开发步骤:
①添加MyBatis的坐标
②创建user数据表
③编写User实体类
④编写映射文件UserMapper.xml
⑤编写核心文件SqlMapConfig.xml
⑥编写测试类
2.MyBatis核心配置文件概述
2.1MyBatis常用配置解析
environments标签
数据库环境的配置,支持多环境配置
<!--指定默认的环境名称-->
<environments default="developement">
<!--指定当前环境的名称-->
<environment id="developement">
<!--指定事务管理类型是JDBC-->
<transactionManager type="JDBC"></transactionManager>
<!--指定当前数据源类型是连接池-->
<dataSource type="POOLED">
<!--数据源配置的基本参数-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
mapper标签
该标签的作用是加载映射的,加载方式有如下几种:
使用相对于类路径的资源引用,例如:
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
使用完全限定资源定位符(URL),例如:
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
使用映射器接口实现类的完全限定类名,例如:
<mapper class="org.mybatis.builder.AuthorMapper"/>
将包内的映射器接口实现全部注册为映射器,例如:
<package name="org.mybatis.builder"/>
properties标签
实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties文件
<properties resource="jdbc.properties"></properties>
<environments default="developement">
<environment id="developement">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
typeAliases标签
类型别名是为Java 类型设置一个短的名字。原来的类型名称配置如下
<select id="findAll" resultType="com.fbst.domain.User"> select * from User</select>
配置typeAliases,为com.fbst.domain.User定义别名为user
<typeAliases>
<typeAlias type="com.fbst.domain.User" alias="user"></typeAlias>
</typeAliases>
<select id="findAll" resultType="user">
select * from User
</select>
上面我们是自定义的别名,mybatis框架已经为我们设置好的一些常用的类型的别名
别名 | 数据类型 |
---|---|
string | String |
long | Long |
int | Integer |
double | Double |
boolean | Boolean |
2.2知识小结
核心配置文件常用配置:
1、properties标签:该标签可以加载外部的properties文件
<properties resource="jdbc.properties"></properties>
2、typeAliases标签:设置类型别名
<typeAliases>
<typeAlias type="com.fbst.domain.User" alias="user"></typeAlias>
</typeAliases>
3、mappers标签:加载映射配置
<mappers>
<mapper resource="com/fbst/mapper/UserMapper.xml"></mapper>
</mappers>
3. MyBatis的映射文件概述
<?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="userMapper">
<select id="findAll" resultType="user">
select * from user
</select>
</mapper>
3.1约束头
<?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">
3.2根标签、命名空间
<mapper namespace="userMapper"></mapper>
< mapper>< /mapper>:根标签
namespace=“userMapper”:命名空间,与下面语句的id一起组成查询的标识
3.3业务操作以及返回的类型
<select id="findAll" resultType="com.fbst.domain.User">
select * from user
</select>
<select>:查询操作,可选的还有insert、update、delete
id=“findAll”:语句的id标识,与上面的命名空间一起组成查询的标识
resultType=“com.fbst.domain.User”:查询结果对应的实体类型
select * from user:要执行的sql语句
4.MyBatis的增删改查操作
4.1 MyBatis的插入数据操作
编写UserMapper映射文件
insert into user values(#{id},#{uname},#{passwd})中的id、username、password对应实体类User的属性名称
<insert id="save" parameterType="com.fbst.domain.User">
insert into user values(#{id},#{uname},#{passwd})
</insert>
编写插入实体User的代码
public void test2() throws IOException {
//模拟user对象
User user = new User();
user.setUname("xxx");
user.setPasswd("abc");
//获得核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//获得session工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得session回话对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//执行操作 参数:namespace+id
sqlSession.insert("userMapper.save", user);
//mybatis执行更新操作 提交事务
//sqlSession.commit();
//释放资源
sqlSession.close();
}
更新操作必须要提交事务,不提交失误信息是不会保存的
mybatis执行更新操作 提交事务:
方式一:sqlSession.insert(“userMapper.save”, user);
方式二:sqlSession.commit();
插入操作注意问题
插入语句使用insert标签
在映射文件中使用parameterType属性指定要插入的数据类型
Sql语句中使用#{实体属性名}方式引用实体中的属性值
插入操作使用的API是sqlSession.insert(“命名空间.id”,实体对象);
插入操作涉及数据库数据变化,所以要使用sqlSession对象显示的提交事务,即sqlSession.commit()
4.2MyBatis的修改数据操作
编写UserMapper映射文件
<update id="update" parameterType="com.fbst.domain.User">
update user set uname=#{uname},passwd=#{passwd} where id=#{id}
</update>
编写修改实体User的代码
public void test3() throws IOException {
//模拟user对象
User user = new User();
user.setId(7);
user.setUname("lucy");
user.setPasswd("123");
//获得核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//获得session工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得session回话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行操作 参数:namespace+id
sqlSession.update("userMapper.update", user);
//mybatis执行更新操作 提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
修改操作注意问题
修改语句使用update标签
修改操作使用的API是sqlSession.update(“命名空间.id”,实体对象);
4.3MyBatis的删除数据操作
编写UserMapper映射文件
<delete id="delete" parameterType="int">
delete from user where id=#{id}
</delete>
编写删除实体User的代码
public void test4() throws IOException {
//获得核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//获得session工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得session回话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行操作 参数:namespace+id
sqlSession.delete("userMapper.delete", 3);
//mybatis执行更新操作 提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
删除操作注意问题
删除语句使用delete标签
Sql语句中使用#{任意字符串}方式引用传递的单个参数
删除操作使用的API是sqlSession.delete(“命名空间.id”,Object);
4.4MyBatis的查询数据操作
编写UserMapper映射文件
<select id="findAll" resultType="user">
select * from user
</select>
编写查询实体User的代码
public void test1() throws IOException {
//获得核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//获得session工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得session回话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行操作 参数:namespace+id
List<User> userList = sqlSession.selectList("userMapper.findAll");
//打印数据
System.out.println(userList);
//释放资源
sqlSession.close();
}
查询操作注意问题
查询语句使用select标签
查询操作使用的API是sqlSession.selectXxx(“命名空间.id”);
查询结果和使用的API返回值类型相同
4.5知识小结
增删改查映射配置与API:
查询数据:List userList = sqlSession.selectList(“userMapper.findAll”);
<select id="findAll" resultType="user">
select * from user
</select>
添加数据:sqlSession.insert(“userMapper.save”, user);
<insert id="save" parameterType="com.fbst.domain.User">
insert into user values(#{id},#{uname},#{passwd})
</insert>
修改数据:sqlSession.update(“userMapper.update”, user);
<update id="update" parameterType="com.fbst.domain.User">
update user set uname=#{uname},passwd=#{passwd} where id=#{id}
</update>
删除数据:sqlSession.delete(“userMapper.delete”, number);
<delete id="delete" parameterType="int">
delete from user where id=#{id}
</delete>
5.MyBatis的Dao层实现方式
5.1传统开发方式
编写UserDao接口
public interface UserMapper {
public List<User> findAll() throws IOException;
}
编写UserDaoImpl实现
public class UserDaoImpl implements UserDao {
public List<User> findAll() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> userList = sqlSession.selectList("userMapper.findAll");
sqlSession.close();
return userList;
}
}
测试传统方式
@Test
public void testTraditionDao() throws IOException {
UserDao userDao = new UserDaoImpl();
List<User> all = userDao.findAll();
System.out.println(all);
}
5.2代理开发方式
采用 Mybatis 的代理开发方式实现 DAO 层的开发,这种方式是我们后面进入企业的主流。
Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper 接口开发需要遵循以下规范:
1、 Mapper.xml文件中的namespace与mapper接口的全限定名相同
<mapper namespace="com.fbst.dao.UserMapper"></mapper>
2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同(select等标签中的id属性)
3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
4、 Mapper接口方法的输出参数类型(返回值)和mapper.xml中定义的每个sql的resultType的类型相同
public User findById(int id);
<select id="findById" parameterType="int" resultType="com.fbst.domain.User">
select * from user where id=#{id}
</select>
5.3知识小结
MyBatis的Dao层实现的两种方式:
手动对Dao进行实现:
传统开发方式
代理方式对Dao进行实现:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
6.MyBatis映射文件深入
6.1动态sql语句
动态sql之if标签
我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
<select id="findByCondition" parameterType="user" resultType="user">
<where>
<if test="id!=0">
and id=#{id}
</if>
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
</where>
</select>
测试代码:
@Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//模拟条件user
User condition = new User();
condition.setId(1);
condition.setUsername("zhangsan");
condition.setPassword("123");
List<User> userList = mapper.findByCondition(condition);
System.out.println(userList);
}
动态sql之foreach标签
循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。
<select id="findByIds" parameterType="list" resultType="user">
<where>
<foreach collection="list" open="id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
测试代码:
@Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//模拟ids的数据
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(2);
List<User> userList = mapper.findByIds(ids);
System.out.println(userList);
}
foreach标签的属性含义如下:
foreach标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
6.2SQL片段抽取
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的,所以上面映射文件可以优化为:
<!--sql语句抽取-->
<sql id="selectUser">select * from user</sql>
<select id="findByCondition" parameterType="user" resultType="user">
<include refid="selectUser"></include>
<where>
<if test="id!=0">
and id=#{id}
</if>
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
</where>
</select>
<select id="findByIds" parameterType="list" resultType="user">
<include refid="selectUser"></include>
<where>
<foreach collection="list" open="id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
6.3知识小结
MyBatis映射文件配置:
<select>:查询
<insert>:插入
<update>:修改
<delete>:删除
<where>:where条件
<if>:if判断
<foreach>:循环
<sql>:sql片段抽取