SSM知识总结

一.Spring

 

1.创建容器

spring有两个父子容器

Servlet WebApplicationContext:控制器(controller)、视图解析器(view resolvers)等相关的bean。通过spring mvc中提供的DispatchServlet来加载配置

Root WebApplicationContext:service层、dao层进行配置,如业务bean,数据源(DataSource)等。一般通过ContextLoaderListener来加载(或者是ClassPathXml或者FileSystemXml)

ContextLoaderListener用于创建ROOT WebApplicationContext,如果我们没有通过ContextLoaderListener来创建Root WebApplicationContext,那么Servlet WebApplicationContext的parent就是null,也就是没有parent context。

创建成功都要调用ServletContext的setAttribute

为什么要有父子容器:

作用: 父子容器的作用在于,当我们尝试从child context(即:Servlet WebApplicationContext)中获取一个bean时,如果找不到,则会委派给parent context (即Root WebApplicationContext)来查找

在service层我们一般使用spring框架, 而在web层则有多种选择,如spring mvc、struts等,如果现在我们想把web层从spring mvc替换成struts,那么只需要将spring-servlet.xml替换成Struts的配置文件struts.xml即可

如果你的项目确定了只使用spring和spring mvc的话,可以没有Root WebApplicationContext,只有Servlet WebApplicationContext

 

2.实例化bean

Sping提供了两种类型的IOC 容器实现:BeanFactory和ApplicationContext(BeanFactory的子类接口),BeanFactory可以通过XmlBeanFactory加载配置文件,Spring Bean一般也是设置为单例模式

bean什么时候实例化

1.如果你使用BeanFactory作为Spring Bean的工厂类,则所有的bean都是在第一次使用该Bean的时候实例化

2.如果你使用ApplicationContext作为Spring Bean的工厂类

如果bean的scope是singleton的,lazy-init为false(默认为false),则 ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候, 直接从这个缓存中取

如果bean的scope是singleton的,lazy-init为true,则该Bean的实例化是在第一次使用该Bean的时候进行实例化

bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化

 

实例化对象过程:实例化对象,设置对象属性,检查Aware相关接口并设置相关依赖(@Autowired,不是用的时候才设进去,而是在对象实例化时就把该对象设置到对应的类中)

注:如果一个bean的lazy-init为false,而它所依赖的bean的lazy-init为true,那么它必须也确保所有上述singleton 依赖bean也被预先初始化,当然也包括设置为延迟实例化的bean

如果使用的是注解配置bean(@Component),需要使用扫描该注解

 

3.spring相关事务

事务(都需要配置DataSourceTransactionManager):

1.java中有JdbcTemplate(封装了JDBC API,需要配置数据源拿到数据库连接connection),通过它可以进行CRUD(相当于stament和preparestament解析sql语句)

如果用了mybatis就不用JdbcTemplate,mybatis会有SqlSessionDaoTemplate(SqlSession的实现类)进行CRUD

2.编程式事务

基于底层API,主要有DataSourceTransactionManager,如果没有mybatis,还要JdbcTemplate

基于transactionTemplate,需要配置transactionTemplate,如果没有mybatis,还要JdbcTemplate

3.声明式事务

基于xml配置,配置 ,如果没有mybatis,还要JdbcTemplate

基于注解, 配置,在service上加 @Transactional则所有方法都时事务

为什么要用事务:数据库操作要么都发生,要么都不发生,如果业务逻辑很多,中间出现bug会导致前面的数据CRUD,后面失败,导致数据不一致,用了事务就会回滚。

 

4.Aop

AOP实现:

AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ(编译时织入,基于继承的机制);而动态代理则以Spring AOP为代表(运行时织入,基于反射技术)

以下的AspectJ是spring为了ioc的结合使用的AspectJ,与完整的AspectJ有差别,底层依是动态代理技术

1.Spring AOP : 通过配置proxyfactorybean,代理对象实现methodinterceptor(方法拦截器,与CGLIB实现不是同一个类),覆写invoke方法

2.基于Aspect Spring AOP: 基于aop-config的xml配置或者使用aspectj注解,没有使用它的编译器和织入器

区别:AspectJ是一个比较牛逼的AOP框架,他可以对类的成员变量,方法进行拦截(跟spring没有什么关系,性能快),编译器时增强

Spring的AOP技术只能是对方法进行拦截,运行时增强

使用时:一般都是用AspectJ注解,Spring AOP要实现很多类繁琐,而且性能比AspectJ慢,只能用在方法上。

 

 

二.SpringMVC

 

1. 执行过程

SSM知识总结_第1张图片

DispatcherServlet前端控制器接收发过来的请求,交给HandlerMapping处理器映射器,HandlerMapping处理器映射器,根据请求路径找到相应的HandlerAdapter处理器适配器(处理器适配器就是那些拦截器或Controller),HandlerAdapter处理器适配器,处理一些功能请求,返回一个ModelAndView对象(包括模型数据、逻辑视图名),ViewResolver视图解析器,先根据ModelAndView中设置的View解析具体视图,然后再将Model模型中的数据渲染到View上

 

2.springmvc文件配置

xml配置:控制层实现Controller接口,xml文件中配置为name="/login",接收login的请求

注解:控制层类或者方法使用@RequestMapping(@RequestMapping 注解的方法叫做 Handler Method - 处理器方法),xml文件配置 (这是SpringMVC为@Controller分发请求所必需的,帮助注册MVC的各种处理器,这个是SpringMVC必须要配置的,因为它声明了@RequestMapping、@RequestBody、@ResponseBody等。并且,该配置默认加载很多的参数绑定方法,比如json转换解析器等)

会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter与ExceptionHandlerExceptionResolver三个bean,其还将提供如下支持:

支持使用ConversionService实例对表单参数进行类型转换,该标签会注册一个默认的ConverService,即FormattingConversionServiceFactoryBean。如果需要使用自定义的ConverService转换类,需要显示定义一个ConverService来覆盖之前的默认实现类

支持使用@NumberFormat和@DateTimeFormat注解完成数据类型的格式化;

支持使用@Valid注解对JavaBean实例进行JSR 303验证;

支持使用@RequestBody和@ResponseBody注解

 

3.url地址解析

@requestmapping里加斜杠和不加斜杠没有大致区别,只不过\代表绝对路径(\项目名\),但这里使用相对路径相当于\项目名\

所以也是对的,一般\符合规范一些(如果时前端页面加斜杠是绝对路径localhost:8080后,没有项目名)

 

4.接收参数

1.方法中直接传实体类(Servlet只能传入request和response,不能直接传实体类,只能通过request获取,而mvc就可以通过反射set方法把值注入到实体类中)。bean的属性名称和请求参数名称相同

2.通过传具体属性如String name,和请求参数名称相同

3.通过传HttpRequest获取数据(servlet常用方式),适用于get,post提交方式

4.通过@pathVariable获取url的数据,URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中

5.通过@RequestParam获取数据,@RequestParam可以接收某个名字(默认是参数名称),默认请求中一定要有相应的参数,否则将报404错误码

6.通过@ModelAttribute(相当于model.addAttribute())

运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中,便于View层使用

运用在一个非请求的方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入到ModelMap中。

注:如果@ModelAttribute(“xxx”)则以xxx为键值,jsp取值通过它,若没有取名,则用参数实体的名称,如:

@ModelAttribute User u,键值名称为user

 

5.返回数据

1.放model域中

在方法参数中加Model model,方法中可以用model.addAttribute添加数据(servlet是httpServeletRequest)

或者在方法中new ModelAndView,添加数据到model里。

model和和request区别:

为什么大多程序在controller中给jsp传值时使用model.addAttribute()而不使用 httpServeletRequest.setAttribute()?

事实上model数据,最终spring也是写到HttpServletRequest属性中,只是用model更符合mvc设计,减少各层间耦合,减少侵入性(因为Model是Spring的组件,Request是J2EE的组件,使用Model而不去使用Request可以减少对J2EE的依赖,也便于调试),

其中model本生就是一个Map的实现类的子类。视图解析器将model中的每个元素都通过request.setAttribute(name, value);添加request请求域中

Model只是用来传输数据的,并不会进行业务的寻址。但是,ModelAndView却是可以进行业务寻址的,就是设置对应的要请求的静态文件,这里的静态文件指的是类似jsp的文件。当然,两者还有一个最大的区别,那就是Model是每一次请求都必须会带着的(在前端向后台请求时,spring会自动创建Model),但是ModelAndView是需要我们自己去新建的。

我通过${test}这个方式取值,优先取Model和ModelMap的,Model和ModelMap是同一个东西,谁最后赋值的就取谁的,然后是request,最后是从session中获取(一般都是把值放到model域中)。

 

2.传json

通过@ResponseBody方式,返回的是json对象,而不是json字符串,返回null时ajax会报错,把datatype去掉(返回为空对象时不是json对象就会跳转到error,返回类型不一致)或者自己封装成json字符串

通过Gson 的toJson方法把对象转换成json字符串,通过response.getWriter()流到jsp页面

或者JsonObject的fromObject方法把对象转换成json字符串,通过response.getWriter()流到jsp页面

传json对象和json字符串区别:

传json对象,不能是null,否则返回到ajax是error是undefined,除非把dataType去掉,返回的数据是new User()(里面数据都没赋值)那么ajax接收的才是null。

而传json字符串,传null的话ajax也会成功接收到显示的是null,如果是没数据那么显示的是""。

JsonObject和Gson区别:

JSONObject在解析的过程中会对get方法进行解析(获取值),而Gson直接通过属性来获取值

后台@requestbody可以把json字符串转换为实体类,后台@responsebody可以把实体类转换成json对象

 

6.返回页面方式

默认是转发,可以配置视图解析器(因为要传数据到前端,所以最好不要更改返回页面方式)

1. 转发方式,return"forward:/xxx.jsp"

2.重定向方式,return"redirect:/xxx.jsp"

 

7.视图渲染

视图渲染的过程是在获取到ModelAndView后的过程

1.把modelview的值放入html中

2.jstl获得值

3.spring表单input标签等其他换为input或者其他,path转为id和name

 

8.mvc常用配置

 

1.类型转换和格式化

对属性对象的输入输出进行格式化,从其本质上讲依然属于"类型转换"的范畴,所以这两个放一起

servlet没有类型转换,转换操作全都要自己手工完成,异常繁琐。

而Spring MVC框架有许多内置的格式化转换器完成常用数据类型转换。

如:NumberFormatter,DateFormatter,PercentFormatter等等

这些都不要我们去写自定义类型转换器类,只要在配置文件中加和bean id="conversionService" ,配置内置的转换器类(如果要加自定义的格式

p:pattern="yyyy/MM/dd",需引入xmlns:p="http://www.springframework.org/schema/p")。

但有时需要编写具有特定功能的类型转换器,就需要我们自定义类型转换器

Converter是一个可以将一种数据类型转换成另一种数据类型的接口,S为源类型,T为目标类型

Formatter是一个可以将一种数据类型转换成另一种数据类型的接口,S源类型必须为String,T为目标类型

一般都用Formatter自定义类型转换器,请求数据都是以String类型获取,所以Web应用使用Formatter更合理。

 

xml需要配置:

ConversionService:只有数据转换功能;

FormattingConversionService:具有数据转换和数据格式化功能(默认)

常用的自定义类型转换器是日期的,因为springmvc默认的日期转换格式是yyyy/MM/dd,所以你想要其他格式的则需要自定义。在mvc:annotation-driven标签里使用conversion-service属性引用我们自定义的参数转换器。

当然也可以使用注解方式,可以放属性上或者set和get方法上

@DatetimeFormat(pattern="yyyy-MM-dd")是将String转换成Date,主要是前台给后台传值时用

pattern 属性值指定的日期时间格式并不是将要转换成的日期格式,这个指定的格式是和传入的参数对应的

@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8") 将时间数据转为json数据 ,一般后台传值给前台时

@JsonFormat 注解不是 Spring 自带的注解,所以使用该注解前需要添加 jackson 相关的依赖包,按照国际标准时间GMT进行格式化的,而在国内默认时区使用的是CST时区,两者相差8小时

@NumberFormat,一般用来格式化有关钱的数据,会自动将你的String类型转为double类型

这个也需要在配置文件中加

 

展现在jsp页面也需要格式化,采用jstl的fmt标签

还有其他方式,虽然可以解决日期数据转换问题,但不太符合规范,简单了解一下。

因为请求中都是String类型,所以可以之间就定义日期为String,或者也可以定义为Date,我们知道mvc是通过反射set方法把值注入到实体类中,通过get方法获取值,所以可以直接修改Date的set方法的参数为string,里面在通过SimpleDateFormat转换成date,get方法返回数据类型为String,这样jsp页面也不需格式化。

 

总的来说:可以直接使用spring内置转换器,或者自定义类型转换器,或者使用格式化注解,还有@InitBinder(可以对 WebDataBinder 对象进行初始化),当然最后提的修改set方法觉得可以也可以加上。

 

2.表单标签库

jsp开头需要引入<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

form标签,input标签,password标签,hidden标签,textarea标签,checkbox标签等等。

用法:标签元素的 id 属性对应 modelAttribute,标签 元素的 name 属性对应 model 中的属性

现在都不用这个,用的都是html标签,因为用了这个在视图渲染中还要转换成html的标签,性能肯定比直接用html的慢,input标签没有html的input属性功能多,而且现在前端页面都很少用jsp编写,尽量不使用。

 

3.拦截器

与servlet的过滤器类似,过滤器和拦截器的区别:

①拦截器是基于java的反射机制的,而过滤器是基于函数回调。

②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑

 

一般ssm项目的web.xml需要配置过滤器解决post的乱码问题。spring MVC实现拦截器两种方式,实现HandlerInterceptor和WebRequestInterceptor。主要用HandlerInterceptor来实现拦截器,覆写preHandle(处理请求之前)和postHandle(处理请求之后)和afterCompletion(视图渲染之后)。

springmvc.xml配置interceptor

运行过程:首先运行preHandle方法,如果preHandle方法返回true则处理请求之后运行postHandle返回视图运行afterCompletion,否则中断执行。

多个拦截器之间:preHandle方法看配置文件的配置interceptor顺序,postHandle方法和afterCompletion方法则按照配置反过来顺序。

HandlerInterceptor和WebRequestInterceptor区别:

1.WebRequestInterceptor的入参WebRequest是包装了HttpServletRequest 和HttpServletResponse的,通过WebRequest获取Request中的信息更简便。

2.WebRequestInterceptor的preHandle是没有返回值的,说明该方法中的逻辑并不影响后续的方法执行,所以这个接口实现就是为了获取Request中的信息,或者预设一些参数供后续流程使用。

3.HandlerInterceptor的功能更强大也更基础,可以在preHandle方法中就直接拒绝请求进入controller方法

 

4.数据验证

数据验证分为客户端验证和服务端验证。

客户端主要是过滤正常用户的误操作,通过JavaScript来实现(可以用validate插件),服务端验证是整个应用阻止非法数据的最后防线。攻击者可以绕过客户端验证直接进行非法输入(或者直接模拟一个假的请求发来),这样可能会引起系统的异常,为了确保数据的合法性,防止用户通过非正常手段提交错误信息,所以必须加上服务器端验证。

先进行的是数据转换,数据转换成功后才进行数据验证。

两种实现方式:spring自带的验证数据和JSR 303数据验证。

 

1.spring自带的验证数据

spring自带的验证数据需要实现Validator接口,验证数据的类可以借助ValidationUtils实现验证

supports(Class):表示这个Validator是否支持该Class的实例?

validate(Object, org.springframework.validation.Errors):对提供的对象进行校验,并将校验的错误注册到传入的Errors 对象中,jsp通过取出错误信息,可以通过Spring配置消息属性文件,bean id="messageSource"

 

2.JSR 303数据验证

一个是Hibernate Validator,一个为Apache BVal,我只要用Hibernate Validator(与Hibernate无关,主要是用来数据验证)

需要配置bean id="validator"和

在需要数据验证的实体类在属性使用相应的注解,controller层接收的参数使用@valid,也可以配置消息属性文件,如@NotBlank(message = "{}")

 

5.统一异常处理

1.简单异常处理SimpleMappingExceptionResolver

定义异常处理页面用来获取异常信息的变量名,默认名为exception

2.实现 HandlerExceptionResolver 接口

这种方式只需要实现 resolveException 方法,该方法返回一个 ModelAndView 对象,在方法内部对异常的类型进行判断,然后返回合适的 ModelAndView 对象

配置

3.使用 @ ExceptionHandler 注解在方法上面

使用该注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个Controller里面

 

6.国际化

java国际化思想是将程序中的信息放在资源文件中,程序根据支持的国家及语言环境,读取相应资源文件。资源文件是Key-Value形式,每个key的资源文件是不变的,当value是随国家语言变化而变化。

主要通过Locale和ResourceBundle两个类实现

Locale:用于提供本地信息,称为语言环境,不同国家或者地区采用不同的Locale

ResourceBundle:资源包,包含特定于语言环境的资源对象,与特定语言环境相关的信息通过资源包来提供

spring MVC实现国际化底层则就是用的java国际化。

但这里不能用ResourceBundle加载文件,而是把国际化文件配置bean id="messageSource"里加载,

jsp使用,code为国际消息的key,arguments为替换消息的占位符

 

7.文件的上传与下载

servlet可以通过通过getInputStream()取得上传文件二进制流,或者把请求封装成Part,通过getPart()、getParts()取得上传文件,或者使用ServletFileUpload类

 

spring MVC基于commons-fileupload,使用MultipareFile接口,表单文件上传j配置bean id="multipartResolver",多文件采用集合的形式接收,通过request.getServletContext().getRealPath("upload")获得上传文件的虚拟路径位置,一般都是在tomact目录下,但这个文件路径每次都会因为重新部署到tomact上而会丢失以前上传的文件,所以应该放在该项目路径外。

下载要设置response.setContentType("application/octet-stream;charset=utf-8"),告诉浏览器所输出的内容不是普通文本文件或者html文件,而是一个保存到本地的下载文件

response.setHeader("Content-Disposition", "attachment;fileName=" + name),不直接处理相应的实体内容,而是用户选择将实体内容保存到一个文件中,也就是说点击下载会出现下载框,后面fileName为文件下载名称,但文件名称会出现乱码,因为浏览器默认编码为ISO8859-1,所以需要转码new String(fileName.getBytes("UTF-8"),"ISO-8859-1")。

有时候名字用时间戳表示,因为防止用户上传同样的文件会覆盖掉以前的,如果想保留原文件名也可以在数据库加一个字段。

多文件上传也可以借助于前端ueditor插件或者webuploader 插件。

 

三.Mybatis

 

1.mybatis执行过程

1.加载mapper文件,通过mybatis-config.xml的mappers,或者sqlSessionFactory配置mapperLocation,MapperScannerConfigurer去扫描basePackage接口时,在一个包下的xml也会扫描

2.通过SqlSessionFactory配置数据源(或者加载mybatis-config.xml,相当于连接池)获得SqlSession(相当于connection)实现类,只有mapperxml文件由SqlSession操作mapper文件(xml中的命名空间+select的id)进行CRUD。

有mapper接口可以是通过getMapper的代理类(每次都是获取新的代理类),获得接口代理来进行CRUD操作(命名空间要和mapper接口类名相同,select的id要和接口方法相同),其底层还是依赖于最原始的SqlSession的使用方法

3.另外在mybatis-spring结合中,mapper接口在生成动态代理类会自动加上@Component交给spring管理(所以可以不用加@Repository,因为生成的代理类会自动给IOC,所以可以不用去扫描该包下的注解context:component-scan,但如果想自定义一个bean名字@Repository还是可以通过它另取),这样service层就可以通过自动注入进去。

4.MapperScannerConfigurer根据basePackage去扫描该包下的类设置成MapperFactoryBean,通过getObject方法并生成相应的代理类,就不用自己每个去getmapper获取,所以只要dao方法调用,实际会通过代理类的invoke方法调用MapperMethod的execute方法,MappedStatement解析了各种xml的标签语句,通过SqlSession的crud实际调用。

5.mapper接口方法参数:

在mapper接口中加上@param("xxx")注解,则在配置文件中直接用,不加@param用#{index},是第几个就用第几个的索引,索引从0开始,使用List封装参数mapper配置文件使用foreach标签循环list,使用Map封装参数,直接在配置文件引用#{key}即可

resultType默认实体属性和数据库表的属性名称相同,如果不同,则通过resultMap去一个个对应,通过set,get方法映射到实体类,若没找到相应的方法,则通过属性来映射

 

2.具体生成mapper接口代理类

1.mybatis和spring结合生成代理类

MapperScannerConfigurer或者@MapperScan:自动扫描数据映射器接口(同个包下的mapper.xml也会扫描mapperRegister注册添加进去),生成代理类、并注入到Spring的容器中(不然要自己去getmapper生成代理类)。

mapper接口的定义在bean加载阶段会被替换成MapperFactoryBean类型,在spring容器初始化的时候会给我们生成,     MapperFactoryBean类型的对象,在该对象生成的过程中调用afterPropertiesSet()方法,为我们生成了一个MapperProxyFactory类型的对象存放于Configuration里的MapperRegistry对象中,同时解析了mapper接口对应的xml文件,把每一个方法解析成一个MappedStatement对象,存放于Configuration里的mappedStatements。

具体把mapper接口设置成MapperFactoryBean类型:

@MapperScan 获取basePackage或者根据@Mapper获取所在packages,之后通过 ClassPathMapperScanner去扫描包,获取所有Mapper接口类的BeanDefinition,之后具体配置,设置beanClass为MapperFactoryBean,

设置MapperFactoryBean的构造器参数为实际的Mapper接口类,通过ClassPathBeanDefinitionScanner父类进行bean注册,当Mapper接口注入的时候,实际调用的是MapperFactoryBean中的getObject()获取特定的mapper实例(实际上调用getSqlSession().getMapper)

注:MapperScannerConfigurer不用这个类,就必须每个mapper接口自己配置成MapperFactoryBean,把SqlSessionFactory属性传进去

 

2.mybatis生成代理类

mybatis通过getSqlSession().getMapper方法获得代理类,实际上MapperFactoryBean获取代理类也是通过这个方法。

getmapper对应的configuration.getMapper,configuration里parse方法解析映射文件的根节点mapper元素

bindMapperForNamespace是获取namespace属性值对应的Class对象后交给MapperRegistry

MapperRegistry对象维护了所有要生成动态代理类的XxxMapper接口信息,MapperRegistry的addMapper方法是针对这个接口,生成一个MapperProxyFactoy,MapperRegistry的getMapper方法是获取该MapperProxyFactoy创建新的代理类

MapperProxyFactoy实现了InvocationHandler ,所以每次调用mapper接口方法都会回调invoke方法,如果调用的是Object类中定义的方法,直接通过反射调用即可,否则调用mapperMethod.execute

MapperMethod的构造方法中,有两个对象SqlCommand、MethodSignature(MapperMethod的内部类),sqlCommand的getType方法,判断要执行的sql类型INSERT、UPDATE、DELETE、SELECT、FLUSH

(因为内部有个MappedStatement,每个等标签都会被解析成一个MappedStatement对象,并保存到Configuration类中的mappedStatements 属性)

 

3.mapper文件的关联关系

1.一对一

一个人对应一张身份证

实体类设置另一个类为属性

 

mapper实现方法:

嵌套查询 里的column字段值作为里面select的传入值,这种方法必须是另一张有个id和这张表一样,如设置了外键。

嵌套结果

使用POJO存储结果,新建一个新的实体类,把两个类的属性都放到这个实体类(两张表属性太多就不太实用)

 

2.一对多

数据库需要在对应多的那方设置外键

对应一的实体类设置多的一方集合类为属性

如user里要有List ordersList

(id是对应一的那方的id)里的column字段值作为里面select的传入值,只需要一张表select * from user where uid = #{id}

,需要连接两张表

新建一个新的实体类,把两个类的属性都放到这个实体类,需要连接两张表(两张表属性太多就不太实用)

 

3.多对多

数据库创建第三张表存两个实体类的id

实体类都设置另一个实体类为集合属性

因为没在另张表设置外键,这个方法不行

一般都是用这种

,三张表做连接查询

 

4.mybatis知识点

1.mapper文件的namespace是xml的命名空间也是标识,如果有对应的接口类的全路径与namespace属性值完全相同,如果有,就生成这个接口的动态代理类

2.可以typeAliasesPackage属性没model取一个别名,这样每个mapper文件返回数据不用都写全称,另外配置SqlSessionFactory要用sqlSessionFactoryBeanName,因为dataSource还没加载完,SqlSessionFactory就配置进去了,导致dataSource占位符为空报错

3.@Mapper注解标识为这是mapper接口,一般都不用,MapperFactoryBean的构造器参数设置为实际的标注了@Mapper的接口

4.mapper配置文件的增删改查是通过属性名来设置值,如果没这属性名则找该名字的getset方法,两个都有是按属性名来设置。

5.使用#传入参数是,sql语句解析是会加上"",当成字符串来解析,这样相比于$的好处是比较明显对的吧,#{}传参能防止sql注入,如果你传入的参数为 单引号',那么如果使用${},这种方式 那么是会报错的

6.@repository有时候不用写mapperscannerconfigurer的属性basepackage扫描dao接口

它会去将dao这个层中的mapper(也就是我们的接口)都生成实现类,自动生成的实现类中,自动帮我们添加了@Component注解,然后交给spring管理(因为mybatis.xml文件我们最终还是导入了spring容器中)

具体实现dao实体类:

7.配置数据源,BasicDataSource提供了close()方法关闭数据源,设定destroy-method=”close”属性, 以便Spring容器关闭时,数据源能够正常关闭;销毁方法调用close(),是将连接关闭,并不是真正的把资源销毁。而c3p0可以不配置,dbcp没有自动的去回收空闲连接的功能,c3p0有自动回收空闲连接功能,不过dbcp效率比较高。

你可能感兴趣的:(javaWeb)