以下内容是我在自学(小破站找的视频)ssm框架时记录的笔记,之前一直在电脑上保存,为了保存和分享现在把笔记整到csdn,如果有错误和不足的地方欢迎指正,暂时我只记录了这么多,日后我的知识储备多了也会不断补充和完善。
①导入 Spring 开发的基本包坐标
在项目pom.xml文件中导入spring坐标
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.5.RELEASEversion>
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");//通过标签中的id唯一标识获取指定的bean对象
userDao.save();
}
}
①导入坐标
②创建Bean
③创建applicationContext.xml
④在配置文件中进行配置
⑤创建ApplicationContext对象getBean
<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 的垃圾回收器回收了
在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>
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"/>
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"/>
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载
<import resource="文件名.xml"/>
bean标签
id属性:在容器中Bean实例的唯一标识,不允许重复
class属性:要实例化的Bean的全限定名
scope属性:Bean的作用范围,常用是Singleton(默认)和prototype
property标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
import标签:导入其他的Spring的分文件
1)ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件,推荐使用这种
2)FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
3)AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
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);
Spring的重点API
ApplicationContext app = new ClasspathXmlApplicationContext("xml文件")
app.getBean("id")
app.getBean(Class)
注解 | 说明 |
---|---|
@Component | 使用在类上用于实例化Bean |
@Controller | 使用在web层类上用于实例化Bean |
@Service | 使用在service层类上用于实例化Bean |
@Repository | 使用在dao层类上用于实例化Bean |
@Autowired | 使用在字段上用于根据类型依赖注入 |
@Qualifier | 结合@Autowired一起使用用于根据名称进行依赖注入 |
@Resource | 相当于@Autowired+@Qualifier,按照名称进行注入 |
@Value | 注入普通属性 |
@Scope | 标注Bean的作用范围 |
@PostConstruct | 使用在方法上标注该方法是Bean的初始化方法 |
@PreDestory | 使用在方法上标注该方法是Bean的销毁方法 |
首先创建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();
}
}
注解 | 说明 |
---|---|
@Configuration | 用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解 |
@ComponentScan | 用于指定Spring在初始化容器时要扫描的包。作用和在Spring的xml配置文件中的 |
@bean | 使用在方法上,标注将该方法的返回值存储到Spring容器中 |
@PropertySource | 用于加载properties文件中的配置 |
@Important | 用于导入其他配置类 |
创建核心配置类:
@Configuration
@ComponentScan("com.fbst")
public class SpringCofiguration {
}
注解说明:
注解 | 说明 |
---|---|
@Configuration | 标志该类是Spring的核心配置类,相当于一个ApplicationContext.xml文件 |
@ComponentScan(“com.fbst”) | 相当于 |
@PropertySource(“classpath:jdbc.properties”) | 加载properties配置文件 |
@Import({DataSourceConfiguration.class}) | 导入其他副配置文件(DataSourceConfiguration)类 |
开发步骤
①导入spring集成Junit的坐标
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.0.5.RELEASEversion>
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());
}
}
①导入数据源的坐标和数据库驱动坐标
②创建数据源对象
③设置数据源的基本连接数据
④使用数据源获取连接资源和归还连接资源
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.32version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
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
导入Spring坐标
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.5.RELEASEversion>
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();
}
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
<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>
首先,创建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.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.0.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.2.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>5.0.5.RELEASEversion>
dependency>
②在web.xml中配置ContextLoaderListener监听器和全局初始化参数。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-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();
}
}
开发步骤:
①在pom.xml导入Spring、SpringMVC、Servlet和jsp的坐标
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.5.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.0.5.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.0.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.2.1version>
<scope>providedscope>
dependency>
②在web.xml配置SpringMVC的核心控制器
<servlet>
<servlet-name>DispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>DispatcherServletservlet-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" %>
Title
Success!
⑤使用注解配置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"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
<context:component-scan base-package="com.fbst.contorller">context:component-scan>
在配置springmvc前端控制器时添加以下配置,告诉spring-mvc.xml文件位置。
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
⑦客户端发起请求测试
打开浏览器访问:localhost:8080/user/quick
结果:页面显示Success!
①导入SpringMVC相关坐标
②配置SpringMVC核心控制器DispathcerServlet
③创建Controller类和视图页面
④使用注解配置Controller类中业务方法的映射地址
⑤配置SpringMVC核心文件 spring-mvc.xml
⑥客户端发起请求测试
在spring-mvc.xml中配置:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<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 相关坐标
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.5.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.8.4version>
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命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
<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.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.0.5.RELEASEversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
测试代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.save();
}
}
表达式语法:
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(* * . . *. *(…))
通知的配置语法:
名称 | 标签 | 说明 |
---|---|---|
前置通知 | 用于配置前置通知。指定增强的方法在切入点方法之前执行 | |
后置通知 | 用于配置后置通知。指定增强的方法在切入点方法之后执行 | |
环绕通知 | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 | |
异常抛出通知 | 用于配置异常抛出通知。指定增强的方法在出现异常时执行 | |
最终通知 | 用于配置最终通知。无论增强方式执行是否有异常都会执行 |
当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 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>
aop织入的配置
<aop:config>
<aop:aspect ref="切面类">
<aop:after method="通知方法名" pointcut="切点表达式"/>
<aop:after method="通知方法名" pointcut-ref="切点表达式对象引用(id)"/>
aop:aspect>
aop:config>
通知的类型:前置通知、后置通知、环绕通知、异常抛出通知、最终通知
切点表达式的写法:
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
基于注解的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:aspectj-autoproxy/>
⑥测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-anno.xml")
public class AnnoTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.save();
}
}
注解通知的类型
通知的配置语法:@通知注解(切点表达式)
名称 | 注解 | 说明 |
---|---|---|
前置通知 | @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(){}
}
注解aop开发步骤:
①使用@Aspect标注切面类
②使用@通知注解标注通知方法
③在配置文件中配置aop自动代理
①引入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: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);
}
}
<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>
其中,
例如:
name:切点方法名称
isolation:事务的隔离级别
propogation:事务的传播行为
timeout:超时时间
read-only:是否只读
声明式事务控制的配置要点:
平台事务管理器配置
事务通知的配置
事务aop织入的配置
数据库表:
CREATE TABLE `account` (
`name` varchar(20) DEFAULT NULL,
`money` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
①修改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);
}
}
①使用 @Transactional 在需要进行事务控制的类或是方法上修饰,注解可用的属性同 xml 配置方式,例如隔离级别、传播行为等。
②注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置。
③使用在方法上,不同的方法可以采用不同的事务参数配置。
④Xml配置文件中要开启事务的注解驱动
注解声明式事务控制的配置要点
平台事务管理器配置(xml方式)
事务通知的配置(@Transactional注解配置)
事务注解驱动的配置
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.32version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.6version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
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
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 + '\'' +
'}';
}
}
(在resources目录下创建com/fbst/mapper/UserMapper.xml)
先引入dtd约束头
<mapper namespace="userMapper">
<select id="findAll" resultType="com.fbst.domain.User">
select * from user
select>
mapper>
同样先引入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>
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();
}
}
MyBatis开发步骤:
①添加MyBatis的坐标
②创建user数据表
③编写User实体类
④编写映射文件UserMapper.xml
⑤编写核心文件SqlMapConfig.xml
⑥编写测试类
environments标签
数据库环境的配置,支持多环境配置
<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>
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 Userselect>
配置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 |
核心配置文件常用配置:
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>
<mapper namespace="userMapper">
<select id="findAll" resultType="user">
select * from user
select>
mapper>
<mapper namespace="userMapper">mapper>
< mapper>< /mapper>:根标签
namespace=“userMapper”:命名空间,与下面语句的id一起组成查询的标识
<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语句
编写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()
编写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”,实体对象);
编写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);
编写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返回值类型相同
增删改查映射配置与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>
编写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);
}
采用 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>
MyBatis的Dao层实现的两种方式:
手动对Dao进行实现:
传统开发方式
代理方式对Dao进行实现:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
动态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:代表分隔符
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的,所以上面映射文件可以优化为:
<sql id="selectUser">select * from usersql>
<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>
MyBatis映射文件配置:
<select>:查询
<insert>:插入
<update>:修改
<delete>:删除
<where>:where条件
<if>:if判断
<foreach>:循环
<sql>:sql片段抽取