SSM常见题型

SSM常见题型

SpringBean的作用域

<?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"
	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-4.0.xsd">

	<!-- ★bean的作用域
		可以通过scope属性来指定bean的作用域
			-singleton:默认值。当IOC容器一创建就会创建bean的实例,而且是单例的,每次得到的都是同一个
			-prototype:原型的。当IOC容器一创建不再实例化该bean,每次调用getBean方法时再实例化该bean,而且每调用一次创建一个对象
			-request:每次请求实例化一个bean
			-session:在一次会话中共享一个bean
	 -->
	<bean id="book" class="com.atguigu.spring.beans.Book" scope="prototype">
	 	<property name="id" value="8"></property>
	 	<property name="title" value="红高粱"></property>
	 	<property name="author" value="莫言"></property>
	 	<property name="price" value="10.00"></property>
	 	<property name="sales" value="800"></property>
	</bean>
	
</beans>

Spring支持的常用数据库事务传播属性和事务隔离级别

​ 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
​ 事务的传播行为可以由传播属性指定。Spring定义了7种类传播行为。

事务传播行为类型说明
PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
/**
 * @Transactional注解
 * 	该注解可以添加到类上,也可以添加到方法上
 * 	如果添加到类上,那么类中所有的方法都添加上了事务
 * 	如果添加到方法上,只有添加了该注解的方法才添加了事务
 */
//@Transactional
@Service("bookShopService")
public class BookShopServiceImpl implements BookShopService {

	@Autowired
	private BookShopDao bookShopDao;
	
	//1.请简单介绍Spring支持的常用数据库事务传播属性和事务隔离级别?
	
	/**
	 * 事务的属性:
	 * 	1.★propagation:用来设置事务的传播行为
	 * 		事务的传播行为:一个方法运行在了一个开启了事务的方法中时,当前方法是使用原来的事务还是开启一个新的事务
	 * 		-Propagation.REQUIRED:默认值,使用原来的事务
	 * 		-Propagation.REQUIRES_NEW:将原来的事务挂起,开启一个新的事务
	 * 	2.★isolation:用来设置事务的隔离级别
	 * 		-Isolation.REPEATABLE_READ:可重复读,MySQL默认的隔离级别
	 * 		-Isolation.READ_COMMITTED:读已提交,Oracle默认的隔离级别,开发时通常使用的隔离级别
	 */
	@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED)
	@Override
	public void purchase(int userId, String isbn) {
		//1.获取要买的图书的价格
		double bookPrice = bookShopDao.getBookPriceByIsbn(isbn);
//		System.out.println(bookPrice);
		//2.更新图书的库存
		bookShopDao.updateBookStock(isbn);
		//3.更新用户的余额
		bookShopDao.updateAccountBalance(userId, bookPrice);
//		double bookPriceByIsbn = bookShopDao.getBookPriceByIsbn(isbn);
//		System.out.println(bookPriceByIsbn);
	}

}

@Service("cashier")
public class CashierImpl implements Cashier {

	@Autowired
	private BookShopService bookShopService;
	
	@Transactional
	@Override
	public void checkout(int userId, List<String> isbns) {
		for (String isbn : isbns) {
			//调用BookShopService中买东西的方法
			bookShopService.purchase(userId, isbn);
		}
	}

}

事务并发引起的问题以及如何避免

1,脏读(dirty read)

A事务读取B事务尚未提交的更改数据,并在这个数据基础上操作。如果B事务回滚,那么A事务读到的数据根本不是合法的,称为脏读。在oracle中,由于有version控制,不会出现脏读。

2,不可重复读(unrepeatable read)

A事务读取了B事务已经提交的**更改(或删除)**数据。比如A事务第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。

3,幻读(phantom read)

A事务读取了B事务已经提交的新增数据。**注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。**这两种情况对策是不一样的,对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必须加表级锁,防止在这个表中新增一条数据。

4,第一类丢失更新

A事务撤销时,把已提交的B事务的数据覆盖掉。这种错误会造成非常严重的后果。

5,第二类丢失更新

A事务提交时,把已提交的B事务的数据覆盖掉。这种错误会造成非常严重的后果。

更新丢失——mysql所有事务隔离级别在数据库层面均可避免。

脏读——READ-COMMITTED事务隔离级别以上可以避免。(未提交的事务修改的数据也能读取到而引起的错误数据,RC级别以上可避免)

不可重复读——REPETABLE-READ事务隔离级别以上可避免。(加锁后读取的数据会因为其他事务操作而变化,RR级别以上可避免)

幻读——SERIALIZABLE事务隔离级别可避免。

脏读不可重复读幻读
Read uncommitted(读未提交)
Read committed(读已提交)×
Repeatable read(可重复读)××
Serializable(串行化)×××
隔离级别    描述  
READ UNCOMMITTED(读未提交数据)    允许事务读取未被其他事务提交的变更,脏读、不可重复读和幻读的问题都会出现  
READ COMMITED(读已提交数据)   只允许事务读取已经被其他事务提交的变更,可以避免脏读,但不可重复读和幻读问题仍然会出现  
REPEATABLE READ(可重复读)   确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读,但幻读的问题依然存在  
SERIALIZABLE(串行化)   确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可以避免,但性能十分低  

Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. 
Oracle 默认的事务隔离级别为: READ COMMITED   
Mysql 支持 4 中事务隔离级别. 
Mysql 默认的事务隔离级别为: REPEATABLE READ  

共享锁和排它锁

为了解决并发问题,数据库系统引入锁机制。

基本的封锁类型有两种: 排它锁(Exclusive locks 简记为X锁) 和 共享锁(Share locks 简记为S锁)。

  • 排它锁又称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其它事务在T释放A上的锁之前不能再读取和修改A。
  • 共享锁又称为读锁。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其它事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

SpringMVC中如何解决POST请求中文乱码问题GET的又如何处理呢

@Controller
public class SpringMVCHandler {
	
	public static final String SUCCESS="success";

	//1.SpringMVC中如何解决POST请求中文乱码问题,GET的又如何处理呢
	
	/*
	 * ★测试入参为POJO
	 * Spring MVC会按请求参数名和 POJO属性名进行自动匹配,
	 * 		    自动为该对象填充属性值。支持级联属性
	 */
	@RequestMapping("/testPOJO")
	public String testPOJO(Employee employee) {
		System.out.println("员工的信息是:"+employee);
		return SUCCESS;
	}
}
<!--web.xml过滤器 解决POST请求中文乱码问题-->  
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<!--Tomcat/server.xml 解决GET请求中文乱码问题  65行-->
<Connector URIEncoding="UTF-8"></Connector>

SpringMVC的工作流程

@Controller
public class SpringMVCHandler {
	
	public static final String SUCCESS="success";

	//1.简单的谈一下SpringMVC的工作流程
	
	//处理模型数据方式一:将方法的返回值设置为ModelAndView
	@RequestMapping("/testModelAndView")
	public ModelAndView testModelAndView() {
		//1.创建ModelAndView对象
		ModelAndView mav = new ModelAndView();
		//2.设置模型数据,最终会放到request域中
		mav.addObject("user", "admin");
		//3.设置视图
		mav.setViewName("success");
		return mav;
	}
	/*
	 * ★处理模型数据方式二:方法的返回值仍是String类型,在方法的入参中传入Map、Model或者ModelMap
	 * 	不管将处理器方法的返回值设置为ModelAndView还是在方法的入参中传入Map、Model或者ModelMap,
	 *  SpringMVC都会转换为一个ModelAndView对象
	 */
	@RequestMapping("/testMap")
	public String testMap(Map<String , Object> map) {
		//向Map中添加模型数据,最终会自动放到request域中
		map.put("user", new Employee(1, "韩总", "hybing@atguigu.com", new Department(101, "教学部")));
		return SUCCESS;
	}
	
}

在这里插入图片描述

  1. 用户发起一个request请求,这个请求将会首先到达前端控制器DispatcherServlet中,由DispatcherServlet统一调度其他组件的使用;
  2. DispatcherServlet接收到请求后会调用HandlerMapping处理器映射器,由此得知,这个请求该由哪一个Controller来进行处理(并未调用Controller);
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。DispatcherServlet根据处理器Handler获取HandlerAdapter处理器适配器,执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作,告诉处理器适配器应该要去执行哪个Controller;
  4. HandlerAdapter处理器适配器去执行Handler(Controller,也叫页面控制器),即我们的Controller,然后Handler处理器返回ModelAndView(数据和视图)给HandlerAdapter;
  5. HandlerAdapter再将ModelAndView(数据和视图)返回给DispatcherServlet;
  6. DispatcherServlet将ModelAndView交给ViewReslover视图解析器请求进行视图解析,ViewReslover解析后返回具体View,然后返回真正的视图;
  7. 视图渲染, DispatcherServlet将模型数据填充到request域中,对View进行渲染视图(即将模型数据model填充至视图中;
  8. DispatcherServlet将结果响应给用户;

MyBatis中当实体类中的属性名和表中的字段名不一样

class MyBatisTest {

	//1.MyBatis中当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
	/*
	 * 解决方案:
	 * 	1.写sql语句时起别名
	 * 	2.在MyBatis的全局配置文件中开启驼峰命名规则
	 *  3.在Mapper映射文件中使用resultMap来自定义映射规则
	 */
	
	@Test
	void testGetEmployee() throws IOException {
		//1.创建SqlSessionFactory对象
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		//2.获取sqlSession,sqlSession就相当于JDBC中的connection
		SqlSession sqlSession = sqlSessionFactory.openSession();
		try {
		  //3.获取Mapper对象
		  EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
		  //4.调用EmployeeMapper中获取Employee的方法
		  Employee employee = mapper.getEmployeeById(1);
		  System.out.println(employee);
		} finally {
		  //5.关闭sqlSession
		  sqlSession.close();
		}
	}

}
<!--mybatis-config.xml-->
<settings> 
    <!-- 开启驼峰命名规则 ,可以将数据库中的下划线映射为驼峰命名
    例如:last_name可以映射为lastName
   -->
	<setting name="mapUnderscoreToCamelCase" value="true"/> 
</settings>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值