华清远见-重庆中心-java 框架技术总结

ORM

Object Relational Mapping 对象关系映射

创建Java类的对象,将其属性和数据库表中的字段名之间构建映射关系。

这样通过操作该类创建的一个对象,就能操作数据库中对应的数据表。

ORM框架就是对象关系映射框架,用于建华JDBC。

主流的ORM框架有Hibernate、JPAMyBatisMyBatisPlus

Mybatis

一个半自动化的ORM框架。原本叫做ibatis,后来升级改名为MyBatis。

MyBatis免去了几乎所有的JDBC代码以及设置参数和获取结果集的工作

使用XML文件或注解的形式,将SQL语句映射为持久层(dao层)中的方法

官网https://mybatis.org/mybatis-3/zh/index.html

特点

  • 方便
    • 建华JDBC
  • 解除SQL语句和业务代码的耦合
    • sql和java代码分离,sql写在xml文件中,方便拓展维护。
  • 支持动态SQL
    • 不同的情况下,构造不同的SQL
  • 主流
    • SSM中的M

SSM项目搭建

整体流程

  • 1.创建基于Maven的webapp项目
  • 2.修改web.xml版本为4.0,创建java、resources目录、项目包结构、web-inf下的页面目录
  • 3.导入依赖
    • spring-webmvc
    • mybatis
    • mybatis-spring
    • mysql
    • druid
    • spring-jdbc
    • jstl
  • 4.配置Spring
    • 在resources目录下创建application.xml
    • 配置web.xml
      • 设置全局参数: ,读取application.xml文件
      • 设置全局监听器:ContextLoaderListener,初始化Spring容器
  • 5.配置SpringMVC
    • 创建springmvc.xml
      • 设置内部资源视图解析器:InternalResourceViewResolver,设置前后缀
    • 配置web.xml
      • 设置请求分发器:DispatcherServlet,在其中读取springmvc.xml配置文件
      • 使用过滤器解决请求中文乱码
  • 6.配置MyBatis
    • 创建mybatis-config.xml(官网模板)
    • 在application.xml中注入
      • 数据库连接池Druid:DruidDataSource
      • SQL会话工厂:SQLSessionFactory
      • 映射扫描配置器:MapperScannerConfigurer
  • 7.执行sql语句
    • 创建dao层接口,定义方法
    • 在resources下创建mapper目录,创建sql映射文件(官网模板)

具体步骤

1.创建基于Maven的webapp项目

2.修改web.xml版本为4.0,创建java、resources目录、项目包结构、web-inf下的页面目录

在这里插入图片描述

3.导入依赖

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.23</version>
  </dependency>
  <!--MySQL-->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.31</version>
  </dependency>
  <!--Spring集成JDBC-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.23</version>
  </dependency>
  <!--mybatis-->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.11</version>
  </dependency>
  <!--Spring集成MyBatis-->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.7</version>
  </dependency>
  <!--数据库连接池Druid-->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
</dependencies>

4.配置Spring

  • 在resources目录下创建application.xml
<?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 https://www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描使用了Spring注解的根包-->
    <context:component-scan base-package="ssm01"></context:component-scan>
</beans>
  • 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--通过全局监听器初始化Spring容器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--定义全局参数读取Spring配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application.xml</param-value>
    </context-param>
</web-app>

5.配置SpringMVC

  • 在resoureces下创建springmvc.xml
<?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 https://www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描使用了SpringMVC注解的根包-->
    <context:component-scan base-package="ssm01.controller"></context:component-scan>
    <!--设置页面前缀和后缀-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>
  • 在web.xml中配置DispatcherServlet和中文乱码过滤器
 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--通过全局监听器初始化Spring容器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--定义全局参数读取Spring配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application.xml</param-value>
    </context-param>
    
    <!--SpringMVC-->
    <!--配置DispatcherServlet-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--初始化参数读取SpringMVC配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--过滤器解决中文乱码-->
    <filter>
        <filter-name>encodingFilter</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>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

6.配置MyBatis

  • 在resoureces下创建mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!--设置-->
    <settings>
        <!--开启驼峰命名设置-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启SQL日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
</configuration>
  • 在application.xml中注入
<?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 https://www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描使用了Spring注解的根包-->
    <context:component-scan base-package="ssm01.controller"></context:component-scan>

    <!--注入Druid数据源-->
    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/gamedbb?serverTimezone=Asia/Shanghai"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

    <!--注入MyBatis核心对象SqlSessionFactoryBean-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
        <!--设置数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <!--设置MyBatis配置文件路径-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <!--设置MyBatis的SQL映射文件路径-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    </bean>

    <!--扫描项目中的dao层目录-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--设置MyBatis核心对象SQLSessionFactoryBean的名字-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <!--dao层根包-->
        <property name="basePackage" value="ssm01.dao"></property>
    </bean>

</beans>

7.执行SQL

请添加图片描述

实体类

package ssm01.entity;

public class Hero {
    private int id;
    private  String name;
    private String position;
    private String sex;
    private int jiage;
    private String shelf_date;
	//省略get/set
}

dao层接口

package ssm01.dao;

import org.springframework.stereotype.Repository;
import ssm01.entity.Hero;

import java.util.List;

@Repository
/*使用MyBatis时,数据访问层,只需定义为接口*/
public interface HeroDao {

    /*查询所有*/
    List<Hero> queryAll();
}

service层

package ssm01.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ssm01.dao.HeroDao;
import ssm01.entity.Hero;

import java.util.List;

@Service
public class HeroService {
    @Autowired
    private HeroDao heroDao;

    public List<Hero> queryAll(){
        return heroDao.queryAll();
    }
}

controller层

package ssm01.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import ssm01.dao.HeroDao;
import ssm01.entity.Hero;
import ssm01.service.HeroService;

import java.util.List;

@Controller
@RequestMapping("/hero")
public class HeroController {
    @Autowired
    private HeroService heroService;

    @RequestMapping("/queryAll")
    public String queryAll(Model model){
        List<Hero> list = heroService.queryAll();
        System.out.println(list);
        model.addAttribute("list",list);
        return "heroList";
    }
}

在resources下的mapper目录下,创建sql映射文件,命名通常为“实体类Mapper”,如HeroMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace是该映射文件对应的dao层接口全限定名-->
<mapper namespace="ssm01.dao.HeroDao">

    <!--查询select标签-->
    <!--id对应dao层中的某个方法名-->
    <!--如果实体类中的属性名和表中的字段名一致,加入resultType属性,设置实体的全限定名-->
    <!--<select id="queryAll" resultType="ssm01.entity.Hero">
        select * from hero
    </select>-->

    <!--resultMap标签用于给指定的实体类设置返回结果集映射-->
    <!--id属性自定义该映射名称-->
    <!--type属性指定实体类-->
    <resultMap id="heroMap" type="ssm01.entity.Hero">
        <!--主键字段用id标签,其他字段用result标签-->
        <!--id和result标签都有两个属性 property表示实体类中的属性名 column表示表中的字段名-->
        <id property="id" column="hid"></id>
        <result column="price" property="jiage"></result>
        <!--如果遇到下划线转驼峰命名,无需在这里自定义映射,可以在mybatis的配置文件中设置开启驼峰命名映射-->
        <!--<result column="shelfDate" property="shelf_date"></result>-->
    </resultMap>

    <!--如果实体中的属性和表中的字段名不一致,使用resultMap属性设置自定义的结果集映射-->
    <select id="queryAll" resultMap="heroMap">
        select * from hero
    </select>
</mapper>

jsp页面

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<table>
    <c:forEach items="${list}" var="hero">
        <tr>
            <td>${hero.id}</td>
            <td>${hero.name}</td>
            <td>${hero.position}</td>
            <td>${hero.sex}</td>
            <td>${hero.jiage}</td>
            <td>${hero.shelf_date}</td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

SSM项目搭建补充

通过db.properties文件保存连接数据库的信息

.properties文件称为属性文件,其中的数据以键值对(key=value)的形式保存

  • 在resources目录下新建db.properties文件

    DB_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
    DB_URL=jdbc:mysql://localhost:3306/bookdbb?serverTimezone=Asia/Shanghai
    DB_USERNAME=root
    DB_PASSWORD=123456
    
  • 在application.xml中读取properties文件

    <!--读取properties文件-->
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
    
  • 读取时使用EL表达式访问其中的键

    <!--注入Druid数据源DruidDataSource-->
    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="${DB_DRIVER_CLASS_NAME}"></property>
        <property name="url" value="${DB_URL}"></property>
        <property name="username" value="${DB_USERNAME}"></property>
        <property name="password" value="${DB_PASSWORD}"></property>
    </bean>
    

MyBatis配置文件常用设置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--设置-->
    <settings>
        <!--开启驼峰命名映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启SQL日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
</configuration>

使用BootStrap渲染数据

下载bootstrap的文件夹和jquery,保存到webapp根目录下。

由于在web.xml中,SpringMVC的核心类DispatcherServlet(请求分发器)的映射设置成了“/”,表示所有请求,包含静态资源的请求都会交给SpringMVC处理。

解决无法引入静态资源的问题

  • 在webapp目录下,新建一个目录,通常命名为static。将项目中的静态资源文件都保存于此。

  • 在springmvc.xml中

    <!--映射静态资源目录-->
    <!--location表示要映射的静态资源目录-->
    <!--mapping表示最终通过哪种方式进行访问。这里表示只要以/static开头的请求,都可以访问静态资源目录-->
    <mvc:resourcesmapping="/static/**"location="/static/"></mvc:resources>
    <!--开启注解驱动,有这个标签,SpringMVC就能区分哪个是资源文件,哪个是Controller-->
    <mvc:annotation-driven></mvc:annotation-driven>
    

导入BootStrap的样式和JS文件

<%--导入bootstrap的css文件--%>
<linkhref="${pageContext.request.contextPath}/static/bootstrap-3.4.1-
dist/css/bootstrap.min.css"rel="stylesheet"
   type="text/css">
<%--导入jquery--%>
<scriptsrc="${pageContext.request.contextPath}/static/bootstrap-3.4.1-dist/js/jquery-3.6.2.min.js"></script>
<%--导入boostrap的js文件--%>
<scriptsrc="${pageContext.request.contextPath}/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>

在SpringMVC中,让某个控制层中的方法返回JSON格式的数据

  • 添加依赖

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.14.2</version>
    </dependency>
    
  • @ResponseBody注释

    该注解可以加在类或方法上

    • 如果加在方法上,表示该方法的返回值类型为JSON格式
    • 如果加在类上,表示该类中的所有方法的返回值类型为JSON格式
    package SSM02.controller;
    
    import SSM02.entity.BookType;
    import SSM02.service.BookTypeService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.util.List;
    
    @Controller
    @RequestMapping("/bookType")
    public class BookTypeController {
        @Autowired
        private BookTypeService bookTypeService;
    
        @RequestMapping("/queryAll")
        public String queryAll(){
            List<BookType> bookTypes = bookTypeService.queryAll();
            System.out.println(bookTypes);
            return "";
        }
    
        //如果controller的某个方法返回一个json字符串
        @RequestMapping("/queryAllToJson")
        @ResponseBody//该方法无论返回值是什么,浏览器都能解析为JSON格式字符串
        public List<BookType> queryAllToJson(){
            List<BookType> list = bookTypeService.queryAll();
            return list;
        }
    
    }
    

SSM项目中使用Ajax

ajax依赖于jquery,所以先保证页面中存在jquery.js。

<script>
    /*
    *使用ajax查询所有图书类型
    * 在页面中使用ajax访问后端如果要得到数据,该数据必须是JSON格式
    * */
    $.ajax({
        url:"${pageContext.request.contextPath}/bookType/queryAllToJson",
        success:function (res){
            //这里的res需要所有的类型集合的JSON字符串
            // console.log(res)
            for (var i=0;i<res.length;i++){
                var $opt = $("<option value='" + res[i].typeId+"'>" + res[i].typeName + "</option>")
                $("select[name=typeId]").append($opt);
            }
        }
    })
</script>

在前端页面中使用ajax访问controller时,controller的返回值必须是一个JSON格式的字符串。

所以controller中的方法上要加入@ResponseBody注解

单元测试JUnit

1.导入依赖

如果只在普通的Maven项目中使用,只需导入该依赖

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

如果要在spring的Maven项目中使用,还需要导入一下依赖

<!--spring集成Junit-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.3.23</version>
  <scope>test</scope>
</dependency>

2.创建单元测试类所在目录

在项目的src目录下新建test\java目录。

在这里插入图片描述

3.使用

  • 在test/java目录下创建测试类

  • 在类上加入

    • @ContextConfiguration(“classpath:application.xml”)
    • @RunWith(SpringJUnit4ClassRunner.class)
  • 在类中创建公开的无返回值无参数方法,加入@Test注解

  • 在该方法上右键运行,运行的是当前方法,在类中空白处右键运行,运行的是当前类中的所有测试方法

    import SSM02.dao.BookInfoDao;
    import org.apache.ibatis.logging.stdout.StdOutImpl;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    //解析Spring配置文件
    @ContextConfiguration("classpath:application.xml")
    @RunWith(SpringJUnit4ClassRunner.class)
    public class Test {
        /*单元测试的方法必须是无参数无返回值的公共方法*/
        @org.junit.Test
        public void fun(){
            System.out.println("单元测试");
        }
    
        @Autowired
        private BookInfoDao bookInfoDao;
    
        @org.junit.Test
        public void test1(){
            bookInfoDao.queryAll();
        }
    }
    

MyBatis整理

使用前提

  • 搭建好MyBatis的环境

    • mybatis配置文件模板

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
      
      </configuration>
      
  • 根据表创建实体类

    • 默认属性要和字段名一致
    • 如果表中的字段名使用下划线分割单词,实体属性使用驼峰命名法,在mybatis的配置文件中加入开启驼峰命名方式映射
    <!--设置-->
    <settings>
        <!--开启驼峰命名设置-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启SQL日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
    • 如果表中字段名和实体的属性名既不一致,也不是驼峰命名,就要在写SQL语句时,指定字段名和属性名的映射关系

    • 实体类必须是公共的,其中必须有无参数的构造方法和get/set方法

  • 数据访问层

    • 数据访问层通常是接口(只需要定义方法名和返回值),可以称为dao层或mapper层,命名时可以是xxDao或xxMapper
  • 写接口的SQL映射文件

    • 命名通常为xxxMapper.xml
    • SQL映射文件模板
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="数据访问层接口的全限定名">
    </mapper>
    
    • SQL映射文件可以放在resources目录下,spring的配置文件application.xml通过“classpath:具体路径”读取

      如保存在resources/mapper下

      <!--注入MyBatis核心对象SqlSessionFactoryBean-->
      <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
          <!--设置数据源(引用类型用ref)-->
          <property name="dataSource" ref="dataSource"></property>
          <!--设置MyBatis配置文件路径-->
          <property name="configLocation" value="classpath:mybatis-config.xml"></property>
          <!--设置MyBatis的SQL映射文件路径-->
          <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
      </bean>
      
    • 映射文件也可能放在数据访问层目录下,即dao包下

      IDEA中,如果将xml文件保存在java包下是,默认在target目录(真正运行时的目录)不会加载这些文件,要进行设置,在pom.xml中的build标签中加入以下内容,重新加载

      <!--解决xml如果放在java包下时无法编译的问题-->
      <resources>
        <resource>
            <directory>src/main/java</directory>
          <includes>
            <include>**/*.xml</include>
          </includes>
        </resource>
      </resources>
      

      spring的配置文件application.xml中读取路径正确

      <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
          <!--设置数据源(引用类型用ref)-->
          <property name="dataSource" ref="dataSource"></property>
          <!--设置MyBatis配置文件路径-->
          <property name="configLocation" value="classpath:mybatis-config.xml"></property>
          <!--设置MyBatis的SQL映射文件路径-->
          <property name="mapperLocations" value="classpath:SSM02/dao/mapper/*.xml"></property>
      </bean>
      

查询<select></select>

单表查询

dao中的方法

List<BookType> queryAll();

sql映射文件

  • 当数据库表中的字段名和实体属性一致或开启了驼峰命名映射

    <select id="queryAll" resultType="com.xxx.entity.BookType">
    	select * from book_type
    </select>
    
  • 当数据库表中的字段名和实体属性不一致,使用resultMap

    <select id="queryAll" resultMap="map">
    	select * from book_type
    </select>
    <resultMap id="map" type="com.xxx.entity.BookType">
    	<!--主键使用id标签,其它字段使用result标签-->
        <!--column对应字段名,property对应属性名-->
        <id column="type_id" property="typeId"></id>
        <id column="type_name" property="typeName"></id>
    </resultMap>
    

多表查询

多对一查询

多对一表示多个从表实体对应一个主表实体,如多本图书对应一个图书类型。

在从表实体中,额外添加一个属性:对应的主表的实体对象

public class BookInfo {
    private int bookId;
    private int typeId;
    private String bookName;
    private String bookAuthor;
    private int bookPrice;
    private int bookNum;
    private String publisherDate;
    private String img;
	//多对一查询,额外添加外键对应的实体对象
    private BookType bookType;
}

dao中的方法

List<BookInfo> queryAll();

sql映射文件

  • 关联查询:构建特殊的SQL语句

    • 适合外键对应的表中字段比较少的情况下使用
    <!--sql语句除了查询自身表之外,还要查询关联表中的字段,将其命名为“实体对象.属性”-->
    <select id="queryAll" resultType="SSM02.entity.BookInfo">
            select bi.*,type_name as 'bookType.typeName' from book_info bi,book_type bt where bi.type_id=bt.type_id 
    </select>
    
  • 连接查询(不建议)

    <!--外键关联查询。方式二:关联查询-->
    <select id="queryAll" resultMap="booksMap">
        select *
        from book_info bi,
        book_type bt
        where bi.type_id = bt.type_id
    </select>
    <resultMap id="booksMap" type="SSM02.entity.BookInfo">
        <!--BookInfo中的属性不会自动赋值-->
        <id property="bookId" column="book_id"></id>
        <result property="bookName" column="book_name"></result>
        <result property="typeId" column="type_id"></result>
        <result property="bookAuthor" column="book_author"></result>
        <result property="bookPrice" column="book_price"></result>
        <result property="bookNum" column="book_num"></result>
        <result property="img" column="img"></result>
        <result property="publisherDate" column="publish_date"></result>
        <!--外键对应的实体对象,使用association标签,通过property属性对应实体对象-->
        <association property="bookType">
            <id column="type_id" property="typeId"></id>
            <result column="type_name" property="typeName"></result>
        </association>
    </resultMap>
    
  • 子查询

    • 适合外键对应的表字段比较多的情况
    <!--多表查询,方式三:子查询-->
    <!--1.查询从表-->
    <select id="queryAll" resultMap="booksMap">
        select * from book_info
    </select>
    <!--2.自定义结果映射,使用type_id进行子查询,执行下方的sql-->
    <resultMap id="booksMap" type="SSM02.entity.BookInfo">
        <!--由于使用type_id进行了子查询,所以如果要给type_id赋值,需要再次映射一次-->
        <result column="type_id" property="typeId"></result>
        <!--外键对应的实体对象,使用association赋值-->
        <!--如果这里的子查询来自当前映射文件-->
        <association property="bookType" column="type_id" select="findTypeByTypeId"></association>
    
        <!--如果这里的子查询来自其他dao中的方法-->
        <!--<association property="bookType" column="type_id" select="SSM02.dao.BookTypeDao.findById"></association>-->
    </resultMap>
    <!--3.根据type_id查询完整对象-->
    <select id="findTypeByTypeId" resultType="SSM02.entity.BookType">
        select * from book_type where type_id=#{typeId}
    </select>
    
一对多查询

一对多表示一个主表实体对应多个从表实体。如一个图书类型对应多本图书。

在主表对应的实体类中,额外添加一个属性:多个从表对象的集合

public class BookType {
    private int typeId;
    private String typeName;

    //一对多查询,额外添加一个属性,该类型下的对象集合
    List<BookInfo> books;
}

dao中的方法

BookType queryBooksByType(int typeId);

sql映射文件

  • 连接查询

    <!--一对多查询,方式一:连接查询-->
    <select id="queryBooksByType" resultMap="testMap">
        select *
        from book_info bi inner join book_type bt
        on bi.type_id = bt.type_id
        where bi.type_id = #{typeId}
    </select>
    
    <!--自定义结果映射集-->
    <resultMap id="testMap" type="SSM02.entity.BookType">
        <id property="typeId" column="type_id"></id>
        <result column="type_name" property="typeName"></result>
        <!--集合(List)类型的属性,使用collection标签,使用ofType设置集合中的对象类型-->
        <collection property="books" ofType="SSM02.entity.BookInfo">
            <id column="book_id" property="bookId"></id>
            <result column="book_name" property="bookName"></result>
            <result column="type_id" property="typeId"></result>
            <result column="book_author" property="bookAuthor"></result>
            <result column="book_num" property="bookNum"></result>
            <result column="book_price" property="bookPrice"></result>
            <result column="img" property="img"></result>
            <result column="publisher_date" property="publisherDate"></result>
        </collection>
    </resultMap>
    
  • 子查询

    <!--一对多查询,方式二:子查询-->
    <!--1.根据类型编号查询自身表-->
    <select id="queryBooksByType" resultMap="testMap">
        select * from book_type where type_id = #{typeId}
    </select>
    <!--2.设置结果集映射-->
    <resultMap id="testMap" type="SSM02.entity.BookType">
        <id column="type_id" property="typeId"></id>
        <result column="type_name" property="typeName"></result>
        <!--集合对象,使用collection标签。使用type_id字段执行子查询getBooksByTypeId,将结果映射色到books属性-->
        <collection property="books" column="type_id" select="getBooksByTypeId"></collection>
    </resultMap>
    <!--3.子查询,根据类型编号查询所有对应的图书集合-->
    <select id="getBooksByTypeId" resultType="SSM02.entity.BookInfo">
        select * from book_info where type_id = #{typeId}
    </select>
    
总结
  • 多对一

    如果查询要以从表数据为主,关联主表相应的数据时,属于多对一查询。如查询所有图书的同时,显示其类型。建议使用子查询或自定义特殊的sql语句。都需要在从表实体中添加一个主表对象属性。

    • 主表字段比较少,建议使用自定义特殊的sql语句,保证字段重命名为"主表对象.属性"
    • 主表字段比较多,建议使用子查询,使用标签映射主表对象属性
  • 一对多

    如果查询要以主表数据为主,关联该主键对应的从表实体对象的集合时,属于一对多查询。如查询某个类型,同时显示该类型下的所有图书。建议使用子查询。在主表实体中添加一个从表集合属性。使用**<collection>**标签映射从表集合属性

多条件查询

参考#{}和${}的用法

#{}和${}

在mybatis的sql映射文件中,可以使用#{}和${}表示sql语句中的参数。

#{}相当于预处理,会将参数用?占位后传值

在这里插入图片描述

${}相当于拼接,会将参数原样拼接

通常使用#{},防止sql注入

--#{}会自动用''将参数引起来,如参数为admin
select * from user where username=#{username}
select * from user where username='admin'
--${}会将参数原样拼接,如参数为admin
select * from user where username=${username}
select * from user where username=admin
${}使用情况

如有批量删除的sql,需要传递" 1,2,3,4,5"参数

delete from user where id in(1,2,3,4,5)
int delelteByIds(String ids);
//如实际传递的是"1,2,3,4,5"
<delete id="deleteByIds">
	delete from user where id in (${ids})
</delete>
#{}的使用

在这里插入图片描述

删除<delete></delete>

删除单个

delete from 表 where 字段 = 值

值通常为主键id

删除多个

delete from 表 where 字段 in (数据集合)

如delete from book_info where book_id in (100,101,102)

in后面的内容通常是一个数组

前端页面通过复选框选择要删除的数据,获取选中的数据的id,保存到一个数组中

dao层接口

int deleteByIds(@param("idList")List<Integer> idList)

sql映射文件

<delete id="deleteByIds">
	delete from book_info where book_id in
    <!--
        foreach标签用户遍历dao层传递的集合对象
        collection表示要遍历的集合
		item表示遍历出的每个对象
		separator表示将遍历出的数据用什么分隔
        open和close表示将遍历出的数据使用什么开头和结尾
	-->
    <foreach collection="idList" item="id" separator="," open="(" close=")">
    	#{id}
    </foreach>
</delete>

添加<insert></insert>

添加时的参数虽多,但通常为一个完整的实体对象,所以dao层接口中方法的参数要定义成一个实体对象。

dao层

int insert(BookType bookType) 

sql映射文件

  • 通常加上parameterType参数指定添加的对象实体类全限定名
  • #{}中的参数一定来自于dao层接口方法实体参数对象的属性
  • 如果要在添加成功的同时,获取自动增长的主键值时,要添加
    • useGeneratedKeys="true"表示启动自动获取自增的值
    • keyColumn="type_id"表示自增字段
    • keyProperty="typeId"表示实体类中的主键属性
<insert id="testInsert" useGeneratedKeys="true" keyColumn="type_id" keyProperty="typeId" parameterType="SSM02.entity.BookType">
        insert into book_type values(null,#{typeName})
</insert>

修改<update></update>

修改可以分为修改所有字段和修改部分字段

修改所有字段

dao层

int update(BookInfo bookInfo);

sql映射文件

<update id="update">
    update book_info set
        book_name=#{bookName},
        book_author=#{bookAuthor},
        book_num=#{bookNum},
        book_price=#{bookPrice},
        publisher_date=#{publisherDate}
    where book_id=#{bookId}
</update>

这种方式会修改所有字段,如果实体参数的某个属性没有赋值,就会使用该属性的默认值进行修改

如String类型的属性没有赋值时,就会用null修改,int类型用0修改,如果表汇总该字段非空,就会导致SQL执行异常。

所以修改所有字段,参数为一个完整对象时,保证其中的属性都有值

修改部分字段

方式一

dao层

int updateSth(int bookId,int bookPrice,int bookNum);

sql映射文件

<update id="updateSth">
	update book_info set
    book_num = #{bookNum},
    book_price = #{bookPrice}
    where book_id = #{bookId}
</update>

方式二

dao层

int updateSth(BookInfo bookInfo);

sql映射文件

<update id="updateSth">
	update book_info set
    <if test="bookName!=null">
        book_num = #{bookNum},
    </if>
    <if test="bookPrice!=null">
        book_price = #{bookPrice}
    </if>
    
    where book_id = #{bookId}
</update>

这样写,有以下几个问题

1.如果只有第一个条件满足,最终拼接的SQL语句,会在所有条件后,where关键字之前多出一个逗号,导致语法错误

解决方式:将set替换成<set></set>标签,mybatis会自动去除最后的逗号:

<update id="updateSth">
	update book_info 
    <set>
    <if test="bookName!=null">
        book_num = #{bookNum},
    </if>
    <if test="bookPrice!=null">
        book_price = #{bookPrice}
    </if>
    </set>
    where book_id = #{bookId}
</update>

2.替换为<set>标签后,如果所有提哦啊见都不满足,mybatis会自动去除set部分,SQL语句就会变成update book_info where book_id = ?,导致语法错误

解决方式:在<set>标签中,添加一个不影响原始数据的条件,如<if test="bookId=bookId">book_id=#{bookId}</if> 只需要一个book_id参数,sql语句没有语法错误,对原始数没有任何影响

动态SQL语句

  • <set>搭配<if>用于修改
<update id="testUpdate">
    update book_info
    <set>
        <if test="bookId=bookId">
        	 book_id=#{bookId},
        </if>
        <if test="bookName!=null">
        	book_num = #{bookNum},
    	</if>
    	<if test="bookPrice!=null">
        	book_price = #{bookPrice}
    	</if>
    </set>
    where book_id=#{bookId}
</update>
  • <where>搭配<if>用于查询、修改、删除时的条件
<select id="queryByCondition" resultType="com.xxx.entity.BookInfo">
	select * from book_info
    <where>
    	<if test="bookName!=null">
        	book_name=#{bookName}
        </if>
        <if test="bookAuthor!=null">
        	book_author=#{bookAuthor}
        </if>
        <if test="typeId!=null">
        	and type_id=#{typeId}
        </if>
    </where>
</select>
  • <trim>可以替换self-if和where-if

    该标签有四个属性

    prefix 表示如果trim标签中有if条件满足,就在整个trim部分添加指定前缀

    suffix 表示如果trim标签中有if条件满足,就在整个trim部分添加指定后缀

    prefexOverrides 表示去除整个trim部分多余的前缀

    suffixOverrides 表示去除整个trim部分多余的前缀

使用trim实现修改

可以修改所有字段,也可以修改部分字段

<update id="testUpdate">
    update book_info
    
    <trim prefix="set" suffixOverrides=",">
        book_id=#{bookId},
        <if test="bookName!=null">
            book_name=#{bookName},
        </if>
        <if test="bookAuthor!=null">
            book_author=#{bookAuthor},
        </if>
        <if test="bookPrice!=null">
            book_price=#{bookPrice},
        </if>
        <if test="bookNum!=null">
            book_num=#{bookNum},
        </if>
        <if test="publisherDate!=null">
            publisher_date=#{publisherDate}
        </if>
    </trim>
    where book_id=#{bookId}
</update>
使用trim标签实现多条件查询
<select id="queryByCondition" resultType="SSM02.entity.BookInfo">
    select bi.*,type_name as 'bookType.typeName'
    from book_info bi,book_type bt
    <trim prefix="where" prefixOverrides="and" suffix="order by book_id asc">
        bi.type_id=bt.type_id
        <if test="bookName!=null">
            and book_name like concat ('%',#{bookName},'%')
        </if>
        <if test="bookAuthor!=null">
            and book_author like concat ('%',#{bookAuthor},'%')
        </if>
        <if test="typeId!=0">
            and bt.type_id = #{typeId}
        </if>
    </trim>
</select>

多选删除/多条件查询/分页实现

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 根据所提供的华清远见-c0rtexas9资料路径,在实验中涉及到了Linux系统标准IO的应用实验。Linux系统标准IO是指Linux操作系统提供的一套标准化的IO库,可以用于操作文件、输入输出等。以下是对该实验的简单描述: 这个实验主要是关于Linux系统标准IO的应用实验。在该实验中,我们可以找到程序的源代码,该源代码是用Linux应用程序的方式编写的。通过这个实验,我们可以了解和学习Linux系统标准IO的基本操作和使用方法。 Linux系统标准IO是一套非常强大和灵活的IO库,提供了一系列的函数和方法来操作文件和进行输入输出。在实验源码中,我们可以看到一些常见的标准IO函数,比如fopen、fclose、fprintf和fscanf等。 通过这些函数,我们可以打开和关闭文件,从文件读取数据或向文件写入数据。实验源码中包含了一些常见的操作,比如读取文件、写入文件、复制文件和查找文件等。通过实验,我们可以了解到如何使用这些函数来完成不同的操作。 此外,在实验源码中可能还会涉及到一些其他的Linux系统标准IO相关的知识点,比如文件指针、文件描述符和文件流等。这些知识点对于理解和使用Linux系统标准IO函数非常重要。 通过实验中提供的源代码,我们可以进行相应的实验操作,从而更好地理解和学习Linux系统标准IO的使用。同时,我们也可以通过对实验源码的分析和调试,更深入地了解Linux系统标准IO的内部工作原理。 总之,通过这个实验,我们可以掌握Linux系统标准IO的基本操作和使用方法,从而提高我们在Linux系统中进行文件操作和输入输出的能力。 ### 回答2: 华清远见(英文名称为Far Infrared Technologies International Limited)是一家专注于红外光学技术研发及应用的企业。该公司的产品主要应用于安防监控、无人机、机器人、智能家居等领域。 关于"06. linux系统标准io实验"的实验资料包括了程序源码。在Linux操作系统中,标准I/O(Input/Output)库是用于进行文件读写和输入输出操作的一套API(Application Programming Interface)。标准I/O库提供了一系列函数,包括文件打开、读取、写入、关闭等操作,方便开发人员进行文件操作和输入输出。 这份实验资料中的源码,应该是用于展示和实践Linux系统标准I/O库的使用方法和技巧。通过编译和运行这些源码,可以了解如何使用标准I/O库来进行文件的读写和输入输出操作,包括打开文件、读取文件内容、写入文件等。 这些实验源码可以作为学习和实践Linux系统标准I/O库的参考资料。通过实际操作,可以加深对标准I/O库的理解和掌握,提高在Linux环境下进行文件操作和输入输出的能力。 总之,"06. linux系统标准io实验"的实验资料中的程序源码是用于学习和实践Linux系统标准I/O库的使用方法,通过编译和运行这些源码,可以加深对标准I/O库的理解和掌握,提高在Linux环境下进行文件操作和输入输出的能力。 ### 回答3: 华清远见-c0rtexa9资料中的程序源码目录为\linux应用实验源码\06. linux系统标准io实验\。这个实验中包含了一些关于Linux系统标准输入输出的代码示例。 在Linux中,标准输入输出是三个预先定义好的文件描述符,分别是0(stdin),1(stdout),2(stderr)。这些文件描述符与输入输出设备关联,比如键盘和屏幕。使用标准输入输出可以实现用户与程序之间的交互以及程序的输出显示。 在实验源码中,我们可以看到许多用于标准输入输出的函数,包括printf、scanf、getchar、putchar等。这些函数可以帮助我们进行输入输出操作。 在实验中,我们可以通过这些代码示例学习如何从标准输入读取用户输入,如何向标准输出显示结果。例如,可以使用scanf函数读取用户输入的数据,使用printf函数将处理结果输出显示。 通过实验中的代码示例,我们可以学习到如何处理标准输入输出的错误,如何进行格式化输入输出,如何使用缓冲区进行高效的输入输出等。 总之,华清远见-c0rtexa9资料中的\linux应用实验源码\06. linux系统标准io实验\中包含了一些关于Linux系统标准输入输出的代码示例,通过这些示例我们可以学习到如何进行标准输入输出操作,以及一些与之相关的技巧和注意事项。这对于学习Linux系统编程和开发应用程序非常有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值