零基础学习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>
View Code

 

三 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
    }
}
View Code

配置文件

此处的表达式中的"*"表示返回值为任意

 

 

测试

 

 运行结果

 

posted @ 2019-10-12 11:40  一y样  阅读(383)  评论(0编辑  收藏  举报