MyBatis四

MyBatis四

Mybatis 延迟加载

  • 什么是延迟加载?

    • 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
    • 好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
    • 坏处:因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
  • 一般对于对多查询时使用延迟加载,而对于对一查询时不使用延迟加载。

  • 如:之前的查找用户对应的账户操作时可以使用延迟加载,提高性能

  • 映射文件配置:

    <resultMap type="account" id="accountMap"> 
        <id column="aid" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>
        <!-- 它是用于指定从表方的引用实体属性的 --> 
        <association property="user" javaType="user"> <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
  • SQL语句:SELECT u.*, acc.id id, acc.uid, acc.money FROM user u LEFT JOIN account acc ON u.id = acc.uid

  • 开启延迟加载后的映射文件:

    <resultMap type="account" id="accountMap"> 
        <id column="aid" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>
        <!-- 它是用于指定从表方的引用实体属性的 --> <association property="user" javaType="user"
        select="com.itheima.dao.IUserDao.findById"
        column="uid">
        </association>
    </resultMap>
    
    <select id="findAll" resultMap="accountMap">
        select * from account
    </select>
  • 如何开启延迟加载

    • 在主配置文件中设置

      <settings> 
          <setting name="lazyLoadingEnabled" value="true"/>
          <setting name="aggressiveLazyLoading" value="false"/>
      </settings>

Mybatis 缓存

像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。

Mybatis 中缓存分为一级缓存,二级缓存。

一级缓存

  • 一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。

  • 一级缓存中存放的是实体类对象。

二级缓存

  • 二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

  • 一级缓存中存放的是数据。

  • 共享二级缓存的对象中如果有一个对象对二级缓存所对应的sql语句执行了增删改操作,将会清空该二级缓存区域的数据

  • 二级缓存的开启与关闭:

    1. 在 SqlMapConfig.xml 文件开启二级缓存

      <settings>
      <!-- 开启二级缓存的支持 --> 
          <setting name="cacheEnabled" value="true"/>
      </settings>
    2. 配置相关的 Mapper 映射文件

      • 在映射文件中添加<cache></cache>
    3. 配置对应的想用二级缓存方法

      <select id="findById" resultType="user" parameterType="int" useCache="true">
          select * from user where id = #{uid}
      </select>

Mybatis 注解开发

mybatis 的常用注解说明

@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
  • 使用注解进行一对一查询时,可在@Results对应的@Result中配置,如:

    @Result(column="uid",
            property="user",
            one=@One(select="com.itheima.dao.IUserDao.findById",
            fetchType=FetchType.EAGER) )
  • 使用注解一对多查询时,可在@Results对应的@Result中配置,如:

    @Result(column="id",property="accounts",
            many=@Many(
            select="com.itheima.dao.IAccountDao.findByUid",
            fetchType=FetchType.LAZY
            ) )

mybatis 基于注解的二级缓存

  1. 在主配置文件中配置二级缓存

    <settings>        
        <setting name="cacheEnabled" value="true"/>
    </settings>
  2. 在持久层接口中使用注解配置二级缓存

    @CacheNamespace(blocking=true)
    public interface IUserDao {}

MyBatis三

MyBatis三

Mybatis 的连接池技术

我们在前面的 WEB 课程中也学习过类似的连接池技术,而在 Mybatis 中也有连接池技术,但是它采用的是自己的连接池技术。在 Mybatis 的SqlMapConfig.xml 配置文件中,通过<dataSource type=”pooled”>来实现Mybatis中连接池的配置。

1. Mybatis 连接池的分类

Mybatis 将它自己的数据源分为三类:

  1. UNPOOLED 不使用连接池的数据源
  2. POOLED 使用连接池的数据源
  3. JNDI 使用 JNDI 实现的数据源

2. PooledDataSource 工作原理

tTfPf0.png

Mybatis 的事务控制

1. Mybatis 自动提交事务的设置

连接池中取出的连接,都会将调用connection.setAutoCommit(false)方法,这样我们就必须使用sqlSession.commit()方法,相当于使用了 JDBC中的connection.commit()方法实现事务提交。

因此可以这样取出连接session = factory.openSession(true);


Mybatis 的动态 SQL 语句

1. 动态 SQL 之< if>标签

例如:

<select id="findByUser" resultType="user" parameterType="user">
    select * from user where 1=1
    <if test="username!=null and username != '' ">
    and username like #{username}
    </if> 
    <if test="address != null">
    and address like #{address}
    </if>
</select>

2. 动态 SQL 之< where>标签

例如:

<select id="findByUser" resultType="user" parameterType="user">
    <include refid="defaultSql"></include> 
    <where> 
        <if test="username!=null and username != '' ">
        and username like #{username}
        </if> 
        <if test="address != null">
        and address like #{address}
        </if>
    </where>
</select>

3. 动态标签之< foreach>标签

QueryVo 中有一个 List 集合用于封装参数

配置文件例如:

<!-- 查询所有用户在 id 的集合之中 --> 
<select id="findInIds" resultType="user" parameterType="queryvo">
    <!-- select * from user where id in (1,2,3,4,5); --> 
    <include refid="defaultSql"></include> 
    <where> 
        <if test="ids != null and ids.size() > 0"> <foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
            #{uid}
        </foreach>
        </if>
    </where>
</select>
  • <foreach>标签用于遍历集合,它的属性:
  1. collection:代表要遍历的集合元素,注意编写时不要写#{}
  2. open:代表语句的开始部分
  3. close:代表结束部分
  4. item:代表遍历集合的每个元素,生成的变量名
  5. sperator:代表分隔符

Mybatis 多表查询之一对一(多对一)

方式一:

  • 定义一个实体类继承其中一方的实体类,然后属性增加另一实体类中的是属性作为属性。

  • 如:Account和User,定义一个AccountUser类继承Account类,然后将想要的User中的属性加入AccountUser中,比如添加username和address两个属性,从而可以完成一对一的查询,一个AccountUser中包含了一个Account对应的一个User。

  • 小结:定义专门的 po 类作为输出类型,其中定义了 sql 查询结果集所有的字段。此方法较为简单,企业中使用普遍。

方式二:

使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。
通过面向对象的(has a)关系可以得知,我们可以在 Account 类中加入一个 User 类的对象来代表这个账户是哪个用户的。

  • 在Account中增加一个User属性,用于表示这个Account属于哪个User。

  • 同时还要修改对应的映射配置文件,如下修改

    <!-- 建立对应关系 --> 
    <resultMap type="account" id="accountMap"> 
        <id column="aid" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>
        <!-- 它是用于指定从表方的引用实体属性的 --> 
        <association property="user" javaType="user"> 
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>

一对多查询

  • 需求:

    • 查询所有用户信息及用户关联的账户信息。
  • 分析:
    用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,我们想到了左外连接查询比较合适。

  • 可以在User类中增加一个Account是Set集合。

  • 映射文件配置:

    <resultMap type="user" id="userMap"> <id column="id" property="id">
        </id> <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>
        <!-- collection 是用于建立一对多中集合属性的对应关系
        ofType 用于指定集合元素的数据类型 --> 
    
        /* property="accList":关联查询的结果集存储在 User 对象的上哪个属性。
        ofType="account":指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名 */
    
        <collection property="accounts" ofType="account">
            <id column="aid" property="id"/>
            <result column="uid" property="uid"/>
            <result column="money" property="money"/>
        </collection>
    </resultMap>
  • SQL语句:SELECT u.*, acc.id id, acc.uid, acc.money FROM user u LEFT JOIN account acc ON u.id = acc.uid


Mybatis 多表查询之多对多

  • 多对多关系其实我们看成是双向的一对多关系。

  • 拿用户与角色举例,一个用户可以有多个角色,一个角色又可以有多个用户。
    tTb2E8.png

  • 需求:

    • 实现查询所有对象并且加载它所分配的用户信息。
  • 分析:

    • 查询角色我们需要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE 表)才能关联到用户信息。
  • SQL语句:

    SELECT
    r.*,u.id uid,
    u.username username,
    u.birthday birthday,
    u.sex sex,
    u.address address
    FROM 
    ROLE r
    INNER JOIN 
    USER_ROLE ur
    ON ( r.id = ur.rid)
    INNER JOIN
    USER u
    ON (ur.uid = u.id);
  1. 实现角色到用户的一对多

    • 在角色实体类中加入一个用户的Set集合
    • 编写dao接口
    • 配置映射文件
  2. 实现用户到角色的一对多

    • 在用户实体类中加入一个角色的Set集合
    • 编写dao接口
    • 配置映射文件
  3. 最终完成多对多查询。

MyBatis二

MyBatis二

自定义MyBatis

tR2AoQ.png

用户在映射配置文件中配置的相关属性

  • resultType 属性:用于指定结果集的类型。

  • parameterType 属性:用于指定传入参数的类型。

  • sql 语句中使用#{}字符: 它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。

    <select id="findById" resultType="com.itheima.domain.User" parameterType="int">
        select * from user where id = #{uid}
    </select>

ognl 表达式:

  • 它是 apache 提供的一种表达式语言,全称是:Object Graphic Navigation Language 对象图导航语言
  • 它是按照一定的语法格式来获取数据的。
  • 语法格式就是使用 #{对象.对象}的方式
    • #{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user.而直接写 username。

新增用户的id的返回值:

<!-- 配置保存时获取插入的 id --> 
<selectKey keyColumn="id" keyProperty="id" resultType="int">
    select last_insert_id();
</selectKey>

#{}与${}的区别

  1. #{}表示一个占位符号:

    • 通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,
    • #{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{}括号中可以是 value 或其它名称。
  2. ${}表示拼接 sql 串

    • 通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。

定义resultMap

为什么要定义?

  • resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类
    型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。

  • 定义

    <!-- 建立 User 实体和数据库表的对应关系
        type 属性:指定实体类的全限定类名
        id 属性:给定一个唯一标识,是给查询 select 标签引用用的。
    --> 
    <resultMap type="com.itheima.domain.User" id="userMap"> 
        <id column="id" property="userId"/>
        <result column="username" property="userName"/>
        <result column="sex" property="userSex"/>
        <result column="address" property="userAddress"/>
        <result column="birthday" property="userBirthday"/>
    </resultMap>
    
    id 标签:用于指定主键字段
    result 标签:用于指定非主键字段
    column 属性:用于指定数据库列名
    property 属性:用于指定实体类属性名称
  • 映射配置使用

    <!-- 配置查询所有操作 --> <select id="findAll" resultMap="userMap">
        select * from user
    </select>

properties(属性)

  • 第一种

    //properties标签内容
    <properties> 
        <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbc.url" value="jdbc:mysql://localhost:3306/eesy"/>
        <property name="jdbc.username" value="root"/>
        <property name="jdbc.password" value="1234"/>
    </properties>
    
    //datasource内容
    <dataSource type="POOLED"> 
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </dataSource>
  • 第二种

    //properties标签内容
    <properties url=file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.properties">
    </properties>
    
    //datasource内容
    <dataSource type="POOLED"> 
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </dataSource>
    • 此时外部文件种的内容
      jdbc.driver=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/eesy
      jdbc.username=root
      jdbc.password=1234

typeAliases(类型别名)

  • 在 SqlMapConfig.xml 中配置:

    <typeAliases>
    <!-- 单个别名定义 --> 
        <typeAlias alias="user" type="com.itheima.domain.User"/>
    <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --> 
        <package name="com.itheima.domain"/>
        <package name="其它包"/>
    </typeAliases>

mappers标签下定义package

注册指定包下的所有 mapper 接口
如:<package name="cn.itcast.mybatis.mapper"/>
  • 使用这种方法就不需要再写mapper以及class或者resource了,因为它会自己找到包下的dao接口以及它所对应的映射配置文件。

MyBatis一

MyBatis一

什么是框架?

  • 它是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题。
  • 使用框架的好处:
    • 框架封装了很多的细节,使开发者可以使用极简单的方式实现功能。大大提高开发效率。

MyBatis

  • 概述:

    • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作,只关注sql语句本身。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。使用了ORM思想。
  • ORM:

    • Object Relational Mapping 对象关系映射
    • 简单的说,就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就实现操作表

入门

环境搭建

  • MyBatis的dependcy依赖:

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>x.x.x</version>
    </dependency>
  • 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>
        <!-- 配置环境 -->
        <environments default="mysql">
            <!-- 配置mysql的环境 -->
            <environment id="mysql">
                <!-- 配置事务的类型 -->
                <transactionManager type="JDBC"></transactionManager>
                <!-- 配置连接池 -->
                <dataSource type="POOLED">
                    <!-- 配置连接数据库的四个基本信息 -->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="uri" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT"/>
                    <property name="username" value="root"/>
                    <property name="password" value="000000"/>
                </dataSource>
            </environment>
        </environments>
    
        <!-- 指定映射配置文件的位置,指的是每个dao独立的配置文件位置 -->
        <mappers>
            <mapper resource="MyBatis1/dao/UserDao.xml"></mapper>
        </mappers>
    </configuration>
  • MyBatis的映射配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="MyBatis1.dao.UserDao">
        <!-- 配置查询所有 -->
        <select id="findAll" resultType="MyBatis1.domain.User">
            select * from user ;
        </select>
    </mapper>
  • 步骤

    1. 创建maven工程并导入坐标
    2. 创建实体类和dao的接口
    3. 创建MyBatis的主配置文件
    4. 创建映射配置文件

注意事项:

  1. 创建映射文件xml位置必须要和对应的dao接口的包结构相同。

  2. 在idea中创建目录时,和包不一样,用点连着创建的目录是一个一级目录,不是多级目录

  3. 映射配置文件的mapper标签的namespace属性的取值必须是dao接口的全限定类名

  4. 映射配置文件的操作配置(select…)id属性的取值必须是dao接口的方法名

  • 好处: 当我们这么写了以后,就不用再写实现类了,MyBatis会帮我们实现。

使用注解配置

  1. 把映射配置文件移除,在dao接口的方法上使用@Select注解,并且指定sql语句
  2. 把主配置文件中mapper中,使用class属性指定dao接口的全限定类名

Collection集合

Collection集合

java.util.Collection接口

  • 所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法

  • 任意的单列集合都可以使用Collection接口中的方法

tc3XP1.md.jpg

Foreach增强for循环

  • 增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写

  • 是jdk1.5之后出现的新特性

  • Collection< E >extends Iterable< E >:所有的单列集合都可以使用增强for循环

  • public interface Iterable< T >实现这个接口允许对象成为 “foreach” 语句的目标。

  • 增强for循环用来遍历集合和数组

    • 格式:

      for(集合或数组的数据类型 变量名:集合名或数组名){
                  sout("变量名");
      }

注意:因为增强for循环本质上是迭代器,所以在循环过程中不能进行增删操作

Iterator迭代器

  • java.util.iterator接口:迭代器(对j集合进行遍历)

  • 两个常用方法:

    1. boolean hasNext(); 如果仍有元素可以迭代,则返回true,没有则返回false
    2. E next(); 返回迭代的下一个元素
  • Iterator是一个接口,无法直接使用,需要一个实现类对象,获取实现类的方式比较特殊

    • Collection接口中有一个方法叫iterator(),这个方法返回的就是迭代器的实现类对象
    • Iterator< E > iterator();
  • 使用步骤:

    1. 使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收
    2. 使用Iterator接口中的方法hasNext()判断还有没有下一个元素
    3. 使用Iterator接口中的方法Next()取出集合中的下一个元素

Set与List

Set

java.uti.Set接口 extends Collection接口

  • 特点:
    1. 不允许存储重复元素
    2. 没有索引

java.uti.HashSet集合 implements Set接口

  • 特点:
    1. 不允许存储重复元素
    2. 没有索引
    3. 是一个无序的集合,存储和取出的顺序有可能不一样
    4. 底层是一个哈希表结构(查询的速度非常快)

java.util.LinkedHashSet extends HashSet集合

  • 特点:
    • 底层是一个哈希表,多了一条链表(记录元素的存储顺序),保证元素有序

List

java.util.List接口 extends Collection接口

  • List接口的特点:

    1. 有序的集合,存储和取出的顺序是一样的(存储123 取出123)

    2. 有索引,包含了一些带索引的方法

    3. 允许存储重复的元素

Java.util.LinkedList集合 implements List接口

  • 底层是一个链表结构,查询慢,增删快

  • 里面包含了大量操作首尾元素的方法

可变参数

  • 可变参数:是JDK1.5之后出来的新特性

  • 使用前提:

    • 当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数。
  • 使用格式:定义方法时使用

    • 修饰符 返回值类型 方法名(数据类型…变量名){}
  • 可变参数的原理:

    • 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
      传递的参数个数,可以是0个(不传递) 1个….多个

注意事项:

  1. 一个方法的参数列表,只能有一个可变参数
  2. 如果方法的参数有多个,那么可变参数必须写在参数列表的末尾

Collections集合工具类

java.util.Collections是集合工具类,用来对集合进行操作,部分方法如下:

  1. public static <T> boolean addAll(Collection<? super T> c, T... elements);将所有指定元素添加到指定 collection 中。

  2. public static void shuffle(List<?> list);使用指定的随机源对指定列表进行置换。

  3. public static <T extends Comparable<? super T>> void sort(List<T> list);根据元素的自然顺序 对指定列表按升序进行排序。

    • 此接口的使用前提:
      • 被排序的集合里面存储的元素必须实现接口Comparable,重写接口中的方法compareTo定义排序的规则
      • 有两种方法:
        1. Comparable:自己和参数比较,自己需要实现Comparable接口,重写比较的规则compareTo方法
        2. Comparator:相当于找一个第三方裁判,比较双方
  4. public static <T> void sort(List<T> list, Comparator<? super T> c);根据指定比较器产生的顺序对指定列表进行排序。

Map

Map

java.util.Map<K,V>接口:HashMap实现类 LinkedHashMap实现类

  • 特点:
    1. 是一个双列集合,一个元素包含两个值(key,value)
    2. key与value的数据类型可以相同,也可以不同
    3. key不允许重复
    4. 一个key只对应一个value

HashMap与LinkedHashMap

  1. HashMap

    • HashMap存储自定义类型键值
    • 作为key的元素,必须重写hashCode方法和equals方法
    • Person同名同年龄为同一个人
    • 底层原理:链表+数组 当长度超过8时变为红黑树
  2. LinkedHashMap

    • java.util.LinkedHashMap< K,V> extends HashMap< K,V>
    • Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序,有序的,存储和取出的顺序一样
    • 底层原理:哈希表 + 链表(记录元素的顺序)

循环遍历

  1. keyset

    • public Set< K> keySet();返回此映射中包含的键的 Set 视图。
    • 通过此方法遍历map集合
  2. entryset

    • public Set<Map.Entry<K,V>> entrySet();返回此映射中包含的映射关系的 Set 视图。
    • 通过此方法遍历map集合

JDK9中的一个特性

  • List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素
    • 使用前提:
      • 当集合中存储的元素个数已经确定了,不在改变时使用
    • 注意:
      1. of方法只适用于List接口,Set接口,Map接口,不适用于接口的实现类
      2. of方法的返回值是一个不能改变的集合,集合不能再使用方法进行元素的添加删除等操作,会抛出异常
      3. Set接口和Map接口在使用时不能有重复的元素,否则会抛出异常

Maven

Maven

Maven的功能

  1. 依赖管理

    • 简单的说就是项目中的jar包不再放在项目中,而是放在Maven仓库中,项目中只存放jar包的坐标,那么就会减小项目的大小,比如如果有十个项目需要用到相同的一些jar包,那么需要在各自的项目中存放jar包,需要十份,而使用Maven,则只需要一份,放入Maven仓库中即可,项目通过对应的jar包坐标去Maven仓库中找到需要的jar包。
  2. 项目的一键构建

    • 项目往往都要经历编译、测试、运行、打包、安装 ,部署等一系列过程。构建就是项目从编译、测试、运行、打包、安装 ,部署整个过程都交给Maven进行管理。整个构建过程,使用Maven一个命令可以轻松完成整个工作。

Maven的安装

  • 与tomcat一样,去官网下载,下载完后是压缩包,然后将压缩包解压到你想要的指定位置即可完成安装。

Maven的环境变量配置

  • 与配置java变量差不多,在环境变量的系统变量中新建一个MAVEN_HOME,值为Maven的解压路径,然后编辑Path系统变量,添加%MAVEN_HOME%\bin。
  • 注意:Maven的配置需要依赖JAVA_HOME。

Maven的仓库和彼此依赖关系

  1. 本地仓库:即在自己的机器上存放jar包的Maven仓库。
  2. 远程仓库:即公司为了管理jar包所专属的一个Maven仓库。
  3. 中央仓库:即互联网中的一个大Maven仓库,存放数以亿计的jar包。
  • 关系:

    1. 如果没有远程仓库,则会先在本地仓库寻找,如果没有则再去中央仓库。(前提:联网。)
    2. 如果有远程仓库,则会先在本地仓库寻找,如果没有则再去远程仓库寻找,如果还没有则最后去中央仓库或者通过本地仓库上传。(前提:和远程仓库在一个局域网。)
  • 修改本地仓库的位置

    • 修改Maven安装目录的conf文件夹下的settings.xnl,添加<localRepository>此处为你的本地仓库的路径</localRepository>

Maven项目标准目录结构

  1. src/main/java目录 核心代码部分
  2. src/main/resources 配置文件部分
  3. src/test/java目录 测试代码部分
  4. src/test/resources 测试配置文件部分
  5. src/main/webapp 页面资源,js,css,图片等

Maven常用命令

  • mvn clean:删除本地编译后的信息,删除本地编译后的target文件夹。
  • mvn compile:编译src/main/java目录下的核心代码部分,将编译后的信息放在target文件夹。
  • mvn test:编译src/test/java目录下的测试代码部分,将编译后的信息放在target文件夹,同时也会编译src/main/java目录下的核心代码部
  • mvn package:编译核心代码部分与测试代码部分,将项目打包,信息存放在target文件夹。
  • mvn install:编译核心代码部分与测试代码部分,将项目打包,信息存放在target文件夹,将包发布到本地仓库。

Maven的生命周期

  • 默认生命周期:compile –> test –> package –> install –> deploy
  • 清理生命周期:clean
  • 站点生命周期

Maven概念模型

tmuMxe.png

IDEA集成Maven插件

  • configure –> Settings –> Maven –> 配置maven的路径以及settings.xml的路径
  • 可以在Runner的VM中添加-DarchetypeCatalog=internal保证不联网时也能创建Maven项目

使用骨架创建Maven的Java工程

  • 在创建Maven工程时勾选Create from archetype,然后选择使用的骨架即可完成创建。
  • 注意:创建完成后没有配置文件的目录,需要手动创建,创建完成后右键make directory as选择对应的配置文件类型。

不使用骨架创建Maven的Java工程

  • 创建时不勾选Create from archetype,其他与用骨架差不多
  • 创建后的项目目录结构与Maven标准目录结构差不多

使用骨架创建Maven的web工程*

  • 在创建Maven工程时勾选Create from archetype,然后选择webapp骨架即可完成创建。
  • 注意:创建完成后只有main下的webapp目录,其他都要自己创建。

解决jar包冲突

  • 可以在对应的depency中加入scope标签,标签内容为provided,意思是只在编译时生效。

Maven的依赖

  • 一个工程依赖另一个工程,会把依赖工程中的jar包传递过来,但是只有scope范围为compile的才能传递。

  • 依赖的排除:设置exclusions标签

Maven版本号统一管理

  • 在pom中设置properties标签,标签内容为自己随便取一个名字作为一个标签,然后其中的标签内容是版本号。
  • 在添加依赖的时候version标签内容可以使用${之前properties中取的名字}来控制版本号。当我们需要修改时直接修改properties即可。

Maven的继承

  • 在工程中使用的一些依赖的版本号可能不同,比如不同工程使用的junit版本号可能不同,操作可能会有些许不同,可以控制它们的版本号相同。
  • 步骤:
    1. 创建一个父工程,打包为pom类型
    2. 在子工程用parent标签声明对父工程的引用
    3. 将子工程中与父工程重复的内容删除(也可以不删)
    4. 在父工程统一管理依赖
    5. 删除子工程中依赖部分的版本号

Maven的聚合

  • 在pom中设置modules标签用于聚合,指定各个子工程的相对路径,然后在聚合工程上安装,所有子工程都会一起被安装。

Jedis

Jedis

一款java操作的redis数据库的工具。

  • 使用步骤:
    1. 下载jedis的jar包
    2. 步骤
      1. 获取连接Jedis jedis = new Jedis(ip地址,端口号)
      2. 进行数据库操作
      3. 关闭连接jedis.close()

Jedis操作各种数据类型

操作各种数据类型的方法名字和命令行中的命令名基本一样

  1. 字符串类型 string
    • set
    • get
    • setex:存储后指定时间过后会自动删除
  2. 哈希类型 hash:就是map格式的
    • hset
    • hget
    • hgetall
  3. 列表类型 list:链表,就是linkedlist格式的
    • lpush/rpush
    • lpop/rpop
    • lrange key start end 范围获取
  4. 集合类型 set:不允许重复元素
    • sadd
    • smembers 获取所有元素
  5. 有序集合类型 sortedset:不允许重复元素,会自动排序。
    • zadd
    • zrange key start end

Jedis连接池:JedisPool

  • 使用:
    1. 可以使用JedisPoolConfig方法创建配置对象然后配置连接池的参数
    2. 创建JedisPool连接池对象,可以空参创建,也可以传入参数创建,比如传入配置对象
    3. 调用方法getResource()方法获取Jedis连接

Jedis连接池工具类

//JedisPool的工具类
public class JedisPoolUtils {

    private static JedisPool jedisPool;

    static {
        InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
        Properties prop = new Properties();
        try {
            prop.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(Integer.parseInt(prop.getProperty("maxTotal")));
        jedisPoolConfig.setMaxIdle(Integer.parseInt(prop.getProperty("maxIdle")));
        jedisPool = new JedisPool(jedisPoolConfig, prop.getProperty("host"), Integer.parseInt(prop.getProperty("port")));
    }

    public static Jedis getJedis() {
        return jedisPool.getResource();
    }

}

Redis

Redis

1. 概念

Redis是一款高性能的NOSQL系列的非关系型数据库。

  1. 什么是NOSQL

    • NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL”,是一项全新的数据库理念,泛指非关系型的数据库。
    • 随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
  2. NOSQL和关系型数据库比较

    • 优点:

      1. 成本:nosql数据库简单易部署,基本都是开源软件,不需要像使用oracle那样花费大量成本购买使用,相比关系型数据库价格便宜。
      2. 查询速度:nosql数据库将数据存储于缓存之中,关系型数据库将数据存储在硬盘中,自然查询速度远不及nosql数据库。
      3. 存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。
      4. 扩展性:关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。
    • 缺点:

      1. 维护的工具和资料有限,因为nosql是属于新的技术,不能和关系型数据库10几年的技术同日而语。
      2. 不提供对sql的支持,如果不支持sql这样的工业标准,将产生一定用户的学习和使用成本。
      3. 不提供关系型数据库对事务的处理。
  3. 非关系型数据库的优势:

    1. 性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
    2. 可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
  4. 关系型数据库的优势:

    1. 复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
    2. 事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库,对方的优势就是自己的弱势,反之亦然。
  5. 总结

    • 关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,
    • 让NoSQL数据库对关系型数据库的不足进行弥补。
    • 一般会将数据存储在关系型数据库中,在nosql数据库中备份存储关系型数据库的数据
  6. 主流的NOSQL产品

    • 键值(Key-Value)存储数据库
      • 相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
      • 典型应用: 内容缓存,主要用于处理大量数据的高访问负载。
      • 数据模型: 一系列键值对
      • 优势: 快速查询
      • 劣势: 存储的数据缺少结构化
    • 列存储数据库
      • 相关产品:Cassandra, HBase, Riak
      • 典型应用:分布式的文件系统
      • 数据模型:以列簇式存储,将同一列数据存在一起
      • 优势:查找速度快,可扩展性强,更容易进行分布式扩展
      • 劣势:功能相对局限
    • 文档型数据库
      • 相关产品:CouchDB、MongoDB
      • 典型应用:Web应用(与Key-Value类似,Value是结构化的)
      • 数据模型: 一系列键值对
      • 优势:数据结构要求不严格
      • 劣势: 查询性能不高,而且缺乏统一的查询语法
    • 图形(Graph)数据库
      • 相关数据库:Neo4J、InfoGrid、Infinite Graph
      • 典型应用:社交网络
      • 数据模型:图结构
      • 优势:利用图结构相关算法。
      • 劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
  7. 什么是Redis

    • Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供测试数据,50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s ,且Redis通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如下:
      1. 字符串类型 string
      2. 哈希类型 hash
      3. 列表类型 list
      4. 集合类型 set
      5. 有序集合类型 sortedset
  8. redis的应用场景

    • 缓存(数据查询、短连接、新闻内容、商品内容等等)
    • 聊天室的在线好友列表
    • 任务队列。(秒杀、抢购、12306等等)
    • 应用排行榜
    • 网站访问统计
    • 数据过期处理(可以精确到毫秒
    • 分布式集群架构中的session分离

2. 下载安装

官网下载,官网下的linux版本,需要windows版本需要去github。

  • redis.windows.conf:配置文件
  • redis-cli.exe:redis的客户端
  • redis-server.exe:redis的服务器端

3. 命令操作

  1. redis的数据结构:

    • redis存储的是:key,value格式的数据,其中key都是字符串,value值有5种不同的数据结构。
      • value的数据结构:
        1. 字符串类型 string
        2. 哈希类型 hash:就是map格式的
        3. 列表类型 list:链表,就是linkedlist格式的
        4. 集合类型 set:不允许重复元素
        5. 有序集合类型 sortedset:不允许重复元素,会自动排序。
  2. 字符串类型 string

    1. 存储:set key value
    2. 获取:get key
    3. 删除:del key
  3. 哈希类型 hash

    1. 存储:hset key field value
    2. 获取:hget key field获取key中指定的值,hgetall key获取key中所有的值
    3. 删除:hdel key field
  4. 列表类型 list:可以添加一个元素到列表的头部或者尾部

    1. 存储
      1. lpush key value:添加至列表的头部
      2. rpush key value:添加至列表的尾部
    2. 获取:lrange key start end 范围获取
    3. 删除
      • lpop key:删除头部元素并返回
      • rpop key:删除尾部元素并返回
  5. 集合类型 set

    1. 存储:sadd key value
    2. 获取:smembers key获取集合中所有元素
    3. 删除:srem key value删除某个元素
  6. 有序集合类型 sortedset

    1. 存储:zadd key score value:给值指定score分数用于排序
    2. 获取:zrange key start end
    3. 删除:zrem key value
  7. 通用命令

    1. keys *:查询所有的键
    2. type key:获取键的数据类型
    3. del key:删除指定的key value

4. 持久化操作

  1. redis是一个内存数据库,当redis服务器重启后,或者电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘的文件中。
  2. redis持久化机制:
    1. RDB:默认方式,不需要进行配置,默认就使用这种机制,在一定的时间间隔内,检测key的变化情况,然后持久化数据。
      1. 编辑redis.conf文件中的save内容
      2. 用命令行指定配置文件打开redis服务器redis-server redis
    2. AOF:日志记录的方式,可以记录每一条指令的操作。每一次命令操作后,持久化数据。
      1. 编辑redis.conf文件中的appendonly内容为yes
      2. 然后进行相应的配置:
        • #appendfsync always:每一次操作都进行持久化
        • appendfsync everysec:每隔一秒进行持久化,默认为这个
        • #appendfsync no:不进行持久化

请我喝杯咖啡吧~

支付宝
微信