零基础学习java------37---------mybatis的高级映射(单表查询,多表(一对一,一对多)),逆向工程,Spring(IOC,DI,创建对象,AOP)
一. mybatis的高级映射
1 单表,字段不一致
resultType输出映射:
要求查询的字段名(数据库中表格的字段)和对应的java类型的属性名一致,数据可以完成封装映射
如果字段和java属性名不一致,则查出来的结果中不一致的那个属性对应的值为null,如下:
Product中书名的属性名为name,但数据库的products表中相应的字段名为book_name
最终查询得到的结果如下(省略了代码部分)
可见查到的name属性为null,解决方法有两种
(1)在查询的sql语句中起别名,如下
(2)手动指定 ,通过resultMap标签
可以手动的指定某个字段封装在哪个属性中
id和result都是映射单列值到一个属性或者字段的简单数据理性,唯一不同的是,id是作为标签的唯一标识,当合其他对象实例对比的时候,这个id很有用,尤其是应用到缓存和内嵌的结果映射
注意;在单表查询的时候,尽量使用resultType来进行映射(别名)
2. 多表查询
2.1 一对一的关联查询
需求:查询订单信息关联查询用户信息
orders表
user表
order与user是一对一的关系
uese与order是一对多的关系
2.1.1. 直接使用sql语句操作数据库来查询,sql语句以及结果如下图
2.1.2 使用mybatis进行次查询查询
有两种方法:建议使用第一种方法,简单
(1)使用resultType进行一对一的数据封装
接口
核心映射文件
测试
最终能得到和上面直接从数据库中查询的结果
(2) 使用resultMap进行一对一的数据封装
结果数据来自多张表,其关心的是表与表之间的数据关系
Order1封装结果数据,订单对用户的关系是一对一的数据关系
接口
核心映射文件
说明:一个实体与另一个实体之间是一对多的关系,那么在一的一方使用 collection 标签,对应多的一方的一个集合,在多的一方使用association标签对应一的一方的一个实体
测试部分
2.2 一对多的关联查询
需求:查询用户信息关联查询订单信息
接口
核心映射文件
测试部分
此处若打印list中的内容,user属性时为null的,因为查出来的值并不是user对象,而是user的属性
二. 逆向工程
能自动封装pojo类,并且生成接口和核心配置文件等
配置文件(generatorConfig.xml)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://10.10.132.200:3306/repay_liuyongtao" userId="DH" password="DH.diKie"> </jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="true" /> </javaTypeResolver> <!-- targetProject:生成PO类的位置 --> <javaModelGenerator targetPackage="com.taotao.pojo" targetProject="./src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.taotao.mapper" targetProject="./src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.taotao.mapper" targetProject="./src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定数据库表 --> <!-- <table schema="" tableName="tb_content"></table> --> <table tableName="repay_case_manager_report" domainObjectName="CaseManagerReport" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> </table> <table tableName="repay_case_manager_change_report" domainObjectName="CaseManagerChangeReport" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> </table> <table tableName="repay_case_manager_relation" domainObjectName="CaseManagerRelation" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> </table> </context> </generatorConfiguration>
三 spring
简介见day16spring文档
优点:
(1)方便解耦,简化开发
(2)AOP编程的支持
(3)声明式事务的支持
(4)方便程序的测试
(5)方便集成各种优秀的框架
(6)降低java EE API的使用难度
(7)java源码是经典学习范例(以后看)
作用:
(1)管理对象和对象之间的依赖关系
(2)作为整合其他优秀框架的介质
(3)AOP简化代码的开发难度
1.
IOC管理对象(一)
1.1 Spring IOC的理解(来源:http://jinnianshilongnian.iteye.com/blog/1413846)
1.1.1 IOC是什么
IOC-Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在java开发中,IOC意味着你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好IOC呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
(1)谁控制谁,控制什么
传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
(2)为何是反转,哪些方面反转了
有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:
当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2-2所示:
1.1.2 IOC能做什么
IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
1.1.3 IOC和DOI
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
(1)谁依赖于谁:当然是应用程序依赖于IoC容器;
(2)为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
(3)谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
(4)注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
IOC管理对象(二)
分享Bromon的blog上对IoC与DI浅显易懂的讲解
(1)IoC(控制反转)
首先想说说IoC(Inversion of Control,控制反转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。
那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
(2)DI(依赖注入)
IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
视频老师讲的
IOC 控制反转,将所有的java对象交给Spring容器来管理。Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans 。
2 创建对象
2.1 基于xml的方式创建对象
(1)将对象的创建配置在xml文件中(application.xml)
简单配置bean的xml文件头信息
配置将要创建的对象
说明:<bean>: 管理对象
<property>: 类中注入的属性
简单数据类型,直接用value(如上),引用数据类型用ref
(2) 加载配置文件=====>生成一个容器
(3) 从容器中获取对象
2.2 创建对象之依赖注入
(1)setter注入
对应的属性一定setter方法
(2)构造注入
即构造方法包含这三个参数
测试类
运行结果
(3)接口注入:spring不支持
2.3 基于注解方式创建对象
1.概述:
注解就是一个特俗的类,在类、方法、属性上面标记特定的注解类,通过反射技术来实现一些特殊的功能
2.优缺点:
优点:开发快
缺点:不利于查询,不直观
3.常用的注解
(1)Component注解:用来取代<bean>标签的配置,一般在不确定层次时使用,可以装配任意bean
【web开发中】
(2)Controller注解:web层
(3)Service注解:service层
(4)Repository注解:持久层
【依赖注入】
注入方式1:按照类型
@Autowired 进行内容注入,可以使用在字段,也可以setter方法。默认按照类型注入。
注入方式2:按照名称
@Qualifier 和 @Autowired 结合修改注入方式,按照名称
注入方式3:按照名称
@Resource(name="名称")
注入方式4:普通值
@Value
【初始化和销毁】
@PostConstruct 初始化
@PreDestroy 销毁
【作用域】
@Scope
@Scope("singleton") 单例
@Scope("prototype") 多例
注意:使用注解创建对象的时候,必须要导入aop这个jar包
3. AOP
3.1 详细了解可看此文:https://www.cnblogs.com/xrq730/p/4919025.html,下面从中摘抄了部分内容
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
AOP核心概念
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
3.2 视频中讲解笔记:
面向切面变成,取代java中的纵向继承以及单继承的局限性,使用动态代理,采取横向切入的方法对目标类的方法进行增强
注意:
1. 目标类实现接口
2. 明确目标类和增强类
3. 切入点表达式
确定目标类的哪个方法需要被增强
(1)方法的签名 com._51doit.aop.UserServiceImpl.add()
(2)expression="execution( 切入点表达式 )
(3)表达式格式:语法 修饰符 返回值 方法签名
a) 修饰符 一般不写
a) 返回值 * 任意
b) 方法签名 com._51doit.aop.UserServiceImpl.add()
c) com._51doit.aop.UserServiceImpl.*(..)
d) com._51doit.*.UserServiceImpl.*(..)
e) com._51doit.*.*Impl.*(..)
案例
增强类:
public class MyAdvice { public void open() { System.out.println("open。。。。。。。。。。。。。"); } public void commit() { System.out.println("commit。。。。。。。。。。。。。"); } }
目标类
接口
public interface UserService { public void add(); public void update () ; public void update(String name); }
实现类
public class UserServiceImpl implements UserService{ @Override public void add() { // TODO Auto-generated method stub System.out.println("add......."); } @Override public void update() { // TODO Auto-generated method stub System.out.println("=====update======="); } @Override public void update(String name) { // TODO Auto-generated method stub } }
配置文件
此处的表达式中的"*"表示返回值为任意
测试
运行结果