Spring概述

一、mybatis嵌套查询

嵌套查询

与前面的关联查询对立,关联查询一次性查询出关联数据,并注入到关联实体中

嵌套查询则是分开两条独立的SQL语句进行查询

案例:部门与员工一对多关系

关联查询SQL语句:(放到Mapper)

select d.id,d.name,e.id eid,e.name ename from t_departments d INNER JOIN t_employees e on d.id=e.dept_id where d.id=1

嵌套查询SQL语句:(放到Mapper-两个Mapper文件)

select * from t_departments where id=1

select * from t_employees where dept_id=1

实体类:部门的实体包含员工集合

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
  private Integer id;
  private String name;
  private String location;

  private List<Emp> emps;  //部门中包含员工集合
}

部门和员工都需要有DAO接口(略)

在mapper文件中,需要从部门的Mapper查询的员工Mapper

<mapper namespace="com.qf.dao.DeptDao">
    <resultMap id="rm" type="dept">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="location" column="location"></result>
        <!-- 一对多关系:column="id"当前部门的id字段传到员工的方法中作为参数
         select="selectByDeptId":调用员工的方法-->
        <collection property="emps" ofType="emp" column="id"
                    select="com.qf.dao.EmpDao.selectByDeptId">
        </collection>
    </resultMap>
    <select id="selectByDeptId" resultMap="rm">
        select * from t_departments where id=#{id}
    </select>
</mapper>

员工Mapper展示:

<mapper namespace="com.qf.dao.EmpDao">
    <select id="selectByDeptId" resultType="emp">
        select * from t_employees where dept_id=#{id}
    </select>
</mapper>

结论:嵌套查询的性能没有关联查询的性能高(关联查询一次性查询,嵌套查询是分多次查询–看日志);所以,通常常用关联查询

懒加载

如果嵌套的表,在项目中用不到,则可以不用加载进来;这样可以提升性能; 例如:我们如果不使用员工信息,则可以不用查询员工表。

在mybatis配置文件中开启懒加载:

<settings>
		<setting name="lazyLoadingEnabled" value="true"/> <!-- 开启延迟加载(默认false) -->
</settings>
DeptDao mapper = MyBatisUtils.getMapper(DeptDao.class);
Dept dept = mapper.selectByDeptId(1);
//设置了懒加载,如果没有用上员工信息,则不会查员工表---提升性能
System.out.println(dept.getName());

二、Spring概述

概述

处在业务层的框架,但是可以做一些控制层和DAO层的整合的事情;主要的功能就是整合

原生的WEB开发的问题:

存在过度耦合:

例如:控制层实例化业务层对象;业务层实例化DAO层对象;有了Spring后,就无需再实例化

Spring是一种非入侵式,移植性强的一种框架

Spring能做什么

Spring从功能角度出发,可以做以下事情:

  1. 整合单元测试
  2. 通过核心工厂产生bean对象(new出来的对象)(工厂模式)
  3. 面向切面编程(AOP),与事务,过滤器等相关(接口回调-代理模式)
  4. 整合DAO层的资源(包括mybatis配置都可整合到Spring中)
  5. 整合SpringMVC控制层资源

三、容器工厂

自定义工厂

模拟Spring工厂的实现,从工厂中获取bean对象

配置文件:

userService=com.qf.a_factory.UserServiceImpl
userDao=com.qf.a_factory.UserDaoImpl

工厂的应用:

public class Factory {
    private Properties p = new Properties();
    public Factory(String config){
        //加载配置文件数据到Properties中
        try {
            InputStream is = Factory.class.getResourceAsStream(config);
            p.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public Object getBean(String key){
        try {
            String path = p.getProperty(key);
            Class c = Class.forName(path);
            return c.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

测试:

public static void main(String[] args) {
    //在表示层(控制层)直接new业务层对象,耦合性太强
    //UserService userService = new UserServiceImpl();
    Factory factory = new Factory("/user.properties");
    UserService userService = (UserService) factory.getBean("userService");
    userService.addUser();
}

spring工厂

通过Spring的核心工厂产生各种bean对象

导入依赖包:

<!-- Spring常用依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

创建spring配置文件(bean工厂)–bean.xml

<!-- 产生bean对象  id:标记名  class:具体实现类-->
<bean id="us" class="com.qf.a_factory.UserServiceImpl"></bean>

Spring测试:

public static void main(String[] args) {
    //获取上下文对象--相当于实例化工厂对象
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    //根据匹配的ID标记,取出bean对象
    UserService us = (UserService) context.getBean("us");
    us.addUser();  //调用业务层的方法
}

配置详解

我们引入了spring的context包,即可将相关的依赖包引入。

注意:Jar包彼此存在依赖,只需引入最外层Jar即可由Maven自动将相关依赖Jar引入到项目中。

四、IOC控制反转

将自身直接实例化的方式,转为由第三方(Spring容器)进行实例化

案例:根据三层架构的案例进行IOC的配置

在业务层引入DAO对象,编写SET方法,通过Spring容器注入bean

public class UserServiceImpl implements UserService {
    //需要进行解耦合:IOC-所有bean都交给spring完成
    private UserDao userDao; //= new UserDaoImpl();

    public void setUserDao(UserDao userDao) { 
        this.userDao = userDao;
    }
    @Override
    public int addUser() {
        System.out.println("调用业务层的addUser");
        userDao.add();
        return 0;
    }
}

Spring工厂中引入bean

<!-- 产生bean对象  id:标记名  class:具体实现类
        ref="ud" 代表引入bean对象   value=""只是值的注入
        name=""  setName方法名首字母小写
    -->
<bean id="us" class="com.qf.a_factory.UserServiceImpl">
    <property name="userDao" ref="ud"></property>
</bean>
<!-- IOC:dao对象需要引入到业务层,充当业务层属性 -->
<bean id="ud" class="com.qf.b_dao.UserDaoImpl"></bean>

五、DI依赖注入

DI与IOC类似,只不过IOC是bean对象的注入,DI是基于属性的赋值。

SET注入

实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String password;
    private String sex;
    private Integer age;
    private Date bornDate;
    private String[] hobbys;
    private Set<String> phones;
    private List<String> names;
    private Map<String,String> countries;
    private Properties files;
}

spring容器的配置:

    <!-- User的实体bean  DI注入  set注入-->
    <bean id="user" class="com.qf.c_entity.User">
        <property name="age" value="30"></property>
        <property name="id" value="11"></property>
        <property name="password" value="123"></property>
        <property name="sex" value="man"></property>
        <property name="bornDate" value="2023/08/09" /><!--注意格式"/"-->

        <!-- 容器的属性注入 -->
        <property name="hobbys">
            <array>
                <value></value>
                <value></value>
                <value></value>
            </array>
        </property>

        <property name="names">
            <list>
                <value>张三丰</value>
                <value>张无忌</value>
            </list>
        </property>

        <property name="phones">
            <set>
                <value>1333333</value>
                <value>1444444</value>
                <value>1555555</value>
            </set>
        </property>
        <property name="countries">
            <map>
                <entry key="a" value="111"></entry>
                <entry key="b" value="222"></entry>
                <entry key="c" value="333"></entry>
            </map>
        </property>

        <property name="files">
            <props>
                <prop key="aaa">张三</prop>
                <prop key="bbb">李四</prop>
            </props>
        </property>
    </bean>

六、总结

1.mybatis嵌套查询
与关联查询的区别;懒加载-没用到嵌套表数据则可以不查询
2.Spring概述(重点)
整合框架;功能-单元测试,容器,AOP,整合控制层和DAO层
3.容器工厂
自定义工厂-模拟编写Spring的工厂;Spring工厂的配置(重点)
4.IOC控制反转(重点)
由Spring容器产生bean对象
5.DI依赖注入(重点)
基于bean对象的属性设置; SET注入