Mybatis从0开始

一、配置maven

在官网中下载mavenMaven – Download Apache Maven

解压下载得压缩包,根据自己的习惯找个目录放进去

 按如下图配置maven系统环境变量,目录请按照自己的写,变量名需要和我的一致,然后验证

 

 配置本地仓库,55行左右

 Maven-Reps是一个文件夹,放在自己常用的盘里,单独的一个文件夹,不要嵌套。配置镜像(默认的是外网的,速度太慢)mirrors标签中其余内容全部注释掉只剩下这一个就ok,也在setting.xml中

<!-- 阿里云仓库 -->
	<mirror>
		<id>alimaven</id>
		<mirrorOf>central</mirrorOf>
		<name>aliyun maven</name>
		<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
	</mirror>

 idea2024配置maven如果打开不是这个界面看下一张图

二、创建maven工程

pom.xml里添加的依赖相当于之前项目中lib目录下的jar包,可在以下链接查找依赖坐标Maven Repository: Search/Browse/Explore (mvnrepository.com)

<dependency> <!-- 依赖开始标签 -->
    <groupId>junit</groupId> <!-- 定义了依赖的组织或公司,这里是JUnit -->
    <artifactId>junit</artifactId> <!-- 定义了依赖的项目名称,这里是JUnit -->
    <version>3.8.1</version> <!-- 定义了依赖的版本号,这里是3.8.1 -->
    <scope>test</scope> <!-- 定义了依赖的范围,这里是测试范围 -->
</dependency> <!-- 依赖结束标签 -->
  • <groupId>:这是依赖的组织或公司的标识符,通常是一个反向域名的形式。这里是junit,表示JUnit这个组织。
  • <artifactId>:这是依赖的项目名称。这里是junit,表示我们依赖的是JUnit项目。
  • <version>:这是依赖的版本号。这里是3.8.1,表示我们依赖的是JUnit的3.8.1版本。
  • <scope>:这是依赖的范围,这里定义为test,表示这个依赖只在测试范围内有效。也就是说,这个JUnit依赖只会在我们执行测试任务时被使用,不会被打包到最终的项目产物中。

总结来说,这段文本配置了一个JUnit依赖,版本为3.8.1,并且只在测试范围内有效。这意味着,当我们运行Maven的测试相关命令时(例如mvn test),Maven会自动下载并使用这个版本的JUnit来进行测试。

三、mybatis入门

1.引入相关依赖

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.10</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.30</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
    </dependency>

 依赖爆红是英文本地仓库没有这个东西,点击这个按钮即可下载

这段文本是Maven项目的pom.xml配置文件的一部分,主要用于指定项目的构建设置。以下是对这段文本的详细解释:

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
    <finalName>untitled1</finalName>
</build>

- <build>:这是Maven项目的构建配置部分的开始标签。
- <resources>:此标签用于指定项目资源文件的位置和配置。
- <resource>:定义了一个资源文件的配置。
  - <directory>src/main/java</directory>:指定资源文件所在的目录,这里是`src/main/java`目录。
  - <includes>:指定要包含的资源文件类型。
    - <include>**/*.properties</include>:包含所有扩展名为`.properties`的文件。
    - <include>**/*.xml</include>:包含所有扩展名为`.xml`的文件。
  - <filtering>true</filtering>:表示在处理这些资源文件时启用过滤功能,即可以使用Maven的过滤机制替换文件中的占位符。
- <finalName>untitled1</finalName>:指定构建后的输出文件名,不包含文件扩展名。这里输出的文件名将是untitled1。

总结来说,这段配置告诉Maven在构建项目时,要包含src/main/java目录下的所有.properties和.xml文件,并对这些文件进行过滤处理,同时指定构建后的输出文件名应为untitled1。

2.自己创建一个数据库,创建mybatis的核心配置文件

mybatis中文文档网站:MyBatis中文网

自行查看文档解析,复制下方红框框的内容,核心配置文件名为:mybatis-config.xml(不可更改),将value后的值替换成自己的

  <!-- 配置环境,默认为development -->
    <environments default="development">
        <environment id="development">
            <!-- 事务管理器类型为JDBC -->
            <transactionManager type="JDBC"/>
            <!-- 数据源类型为连接池 -->
            <dataSource type="POOLED">
                <!-- 数据库驱动 -->
                <property name="driver" value="${driver}"/>
                <!-- 数据库URL -->
                <property name="url" value="${url}"/>
                <!-- 数据库用户名 -->
                <property name="username" value="${username}"/>
                <!-- 数据库密码 -->
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 映射器列表 -->
    <mappers>
        <!-- 引入映射文件 -->
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>

- <environments>: 此元素用于配置多个环境,如开发、测试和生产环境。`default`属性指定了默认使用的环境。
- <environment>: 定义了一个具体的运行环境,包括事务管理器和数据源。
  - <transactionManager>: 指定事务管理方式,这里使用的是`JDBC`类型的事务管理器。
  - <dataSource>: 配置数据源,`type="POOLED"`表示使用连接池。
    - <property>: 设置数据源的属性,如数据库驱动、URL、用户名和密码。`${...}`表示这些值将从外部属性文件或配置中获取。
- <mappers>: 用于指定MyBatis的映射文件,这些文件包含了SQL语句和结果映射的定义。
  - <mapper>: 引入一个具体的映射文件,这里引入了`BlogMapper.xml`文件。

总结来说,这个配置文件设置了MyBatis在开发环境下的数据源和事务管理器,并指定了一个映射文件用于执行SQL语句和映射结果。通过这种方式,MyBatis能够连接到数据库并执行相应的数据操作。

3.创建实体类和mapper接口

在src/main/java目录下

public class User {
    private int id;
    private String name;
    private String pswd;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPswd() {
        return pswd;
    }

    public void setPswd(String pswd) {
        this.pswd = pswd;
    }

    public User() {
    }

    public User(int id, String name, String pswd) {
        this.id = id;
        this.name = name;
        this.pswd = pswd;
    }
}
public interface UserMapper {
    Integer addUser(User user);
}

4.创建映射文件 

在src/main/resources目录下

5.测试

在src/test/java目录下

public class Test1 {
    @Test
    public void test1() throws Exception {
        String recourse = "mybatis-config.xml";
        //读取核心配置文件
        Reader reader = Resources.getResourceAsReader(recourse);
        //初始化mybatis数据库,创建工厂实例
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
        //创建sqlsession实例
        SqlSession session = build.openSession();
        //
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User(1008,"33330","5555");
        Integer i = mapper.addUser(user);
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }
}

6.删、改、查代码

public interface UserMapper {
    //增
    Integer addUser(User user);
    //删
    Integer deleteUser(Integer id);
    //改
    Integer updateUser(User user);
    //全查
    List<User> selectUsers();
    //单查
    User getUser(Integer id);

}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
		PUBLIC "-//mapper.org//DTD Mapper 3.0//EN"
		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper">
	<!--增-->
	<insert id="addUser">
		insert into user value (#{id},#{name},#{pswd});
	</insert>
	<!--删-->
	<delete id="deleteUser" parameterType="java.lang.Integer">
		delete from user where id=#{id};
	</delete>
	<!--改-->
	<update id="updateUser" parameterType="pojo.User">
		update user set name=#{name},pswd=#{pswd} where id=#{id};
	</update>
	<!--全查-->
	<select id="selectUsers" resultType="pojo.User">
		select * from user;
	</select>
	<!--单查-->
	<select id="getUser" resultType="pojo.User" parameterType="java.lang.Integer">
		select * from user where id=#{id};
	</select>
</mapper>
public class Test1 {
    private String recourse = "mybatis-config.xml";
    //读取核心配置文件
    private Reader reader;
    {
        try {
            reader = Resources.getResourceAsReader(recourse);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //初始化mybatis数据库,创建工厂实例
    private SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
    //创建sqlsession实例
    private SqlSession session = build.openSession();

    @Test
    public void add() throws Exception {
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User(1011, "33330", "5555");
        Integer i = mapper.addUser(user);
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

    @Test
    public void delete() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        Integer i = mapper.deleteUser(1008);
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

    @Test
    public void update() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        Integer i = mapper.updateUser(new User(1005, "upp","tt"));
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

    @Test
    public void selectAll() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> i = mapper.selectUsers();
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }
}

四、优化

加入日志功能,首先在pom.xml文件中添加以下依赖,然后在resources文件下创建logback.xml文件

<!--  添加slf4j日志api  -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.20</version>
    </dependency>
    <!--  添加logback-classic依赖  -->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>
    <!--  添加logback-core依赖  -->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.2.3</version>
    </dependency>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%5level [%thread] - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="这个地方写包名,如果只有一级包名就空着">
        <level value="trace"/>
    </logger>
    <root level="error">
        <appender-ref ref="stdout"/>
    </root>
</configuration>

使用lombok简化实体类,在pom.xml中添加相关依赖,之后实体类采用注解的方式

 <!-- lombok依赖包 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.10</version>
      <scope>provided</scope>
    </dependency>
/*
* 实体类
* */
@Data//getter、setter方法
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
@ToString
public class User {
    private int id;
    private String name;
    private String pswd;

    public User(String name, String pswd) {
        this.name = name;
        this.pswd = pswd;
    }
}

五、mybatis标签

1.多条件查询

两种方法

List<User> getUsers(User user);
<!--多条件查询-->
    <!--prefix:设置前缀
    suffix:设置后缀
    suffixOverrides:要去掉的后缀,只去掉最后一个多余的and
    prefixOverrides:要去掉的前缀,只去掉第一个-->
    <select id="getUsers" resultType="pojo.User">
        select *
        from user
        <trim prefix="where" suffix=";" prefixOverrides="or" suffixOverrides="and">
            <if test="id!=null and id!=''">
                id=#{id} and
            </if>
            <if test="name!=null and name!=''">
                or name=#{name} and
            </if>
            <if test="pswd!=null and pswd!=''">
                pswd=#{pswd} and
            </if>
        </trim>

        <!--<where>
            <if test="id!=null and id!=''">
                id=#{id}
            </if>
            <if test="name!=null and name!=''">
                and name=#{name}
            </if>
            <if test="pswd!=null and pswd!=''">
                and pswd=#{pswd}
            </if>
        </where>;-->
    </select>
@Test
    public void selectAll() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> i = mapper.getUsers(new User("zs",null));
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

2.自定义修改

两种方法

Integer updateUser(User user);
    <!--条件修改-->
    <update id="updateUser" parameterType="pojo.User">
        update user
         <trim prefix="set" suffix="where id=#{id}" suffixOverrides=",">
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="pswd!=null and pswd!=''">
                pswd=#{pswd},
            </if>
        </trim>
             <!--<set>
               <if test="name!=null and name!=''">
                   name=#{name},
               </if>
               <if test="pswd!=null and pswd!=''">
                   pswd=#{pswd},
               </if>
            </set>
            where id=#{id}-->
    </update>
    @Test
    public void update() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        Integer i = mapper.updateUser(new User(5, "update2",null));
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

3.自定义新增

Integer addUser(User user);
    <!--自定义新增-->
    <insert id="addUser" parameterType="pojo.User">
        insert into user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id!=null and id!=''">id,</if>
            <if test="name!=null and name!=''">name,</if>
            <if test="pswd!=null and pswd!=''">pswd</if>
        </trim>
        <trim prefix="values(" suffix=")" suffixOverrides=",">
            <if test="id!=null and id!=''">#{id},</if>
            <if test="name!=null and name!=''">#{name},</if>
            <if test="pswd!=null and pswd!=''">#{pswd}</if>
        </trim>
    </insert>
    @Test
    public void add() throws Exception {
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User("33330", null);
        Integer i = mapper.addUser(user);
        System.out.println(i);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

 4.单条件查询

同switch--case,满足条件就跳出判断

User getUserByid(@Param("id") Integer id, @Param("name") String name, @Param("pswd") String pswd);
    <select id="getUserByid" resultType="pojo.User">
        select *
        from user
#         where
            <where>
                <choose>
                    <when test="id!=null and id!=''">id=#{id}</when>
                    <when test="name!=null and name!=''">name=#{name}</when>
                    <when test="pswd!=null and pswd!=''">pswd=#{pswd}</when>
                    <otherwise>1=1</otherwise>
                </choose>
            </where>
    </select>
@Test
    public void selectOne() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        User zs = mapper.getUserByid(5, "zs", null);
        System.out.println(zs);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

5.动态sql(批量操作)

5.1 查

    List<User> selectBatch(@Param("ids") Integer[] ids);
<!--
    collection:要遍历的集合
    open:前缀
    close:后缀
    separator:分隔符
    item:每一个拿到的元素别名
    -->
    <!--in-->
    <select id="selectBatch" resultType="pojo.User" parameterType="java.lang.Integer">
        select *
        from user
        where id in
        <foreach collection="ids" open="(" item="id" separator="," close=")">
            #{id}
        </foreach>
        <!--(<foreach collection="ids" item="id" separator=",">
            #{id}
        </foreach>)-->
    </select>
    <!--or-->
    <!--<select id="selectBatch" resultType="pojo.User" parameterType="java.lang.Integer">
        select *
        from user
        where
        <foreach collection="ids" item="id" separator="or">
            id=#{id}
        </foreach>
    </select>-->
    @Test
    public void selectBatch() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.selectBatch(new Integer[]{1, 2, 3});
        System.out.println(users);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

5.2 删

int delBatch(@Param("ids") Integer[] ids);
    <!--通过id批量删除-->
    <delete id="delBatch" parameterType="java.lang.Integer">
        delete
        from user
        where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>
    @Test
    public void delBatch() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        int res = mapper.delBatch(new Integer[]{7,8,9,10,11});
        System.out.println(res);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

5.3 改 

<!--连接数据库的URL-->
<property name="url" value="jdbc:mysql://127.0.0.1:3306/student?allowMultiQueries=true"/>

int upBatch(@Param("users") List<User> users);
<update id="upBatch">
        <foreach collection="users" item="user">
            update user
            <trim prefix="set" suffix="where id=#{user.id};" suffixOverrides=",">
                <if test="user.name!=null and user.name!=''">
                    name=#{user.name},
                </if>
                <if test="user.pswd!=null and user.pswd!=''">
                    pswd=#{user.pswd},
                </if>
            </trim>
        </foreach>
    </update>
    @Test
    public void upBatch() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        User update1 = new User(1, "update1", null);
        User update2 = new User(2, "update2", null);
        List<User> list = Arrays.asList(update1, update2);
        int res = mapper.upBatch(list);
        System.out.println(res);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

5.4 增

int inBatch(@Param("users") List<User> users);
<insert id="inBatch">
        <foreach collection="users" item="user">
            insert into user
            <trim prefix="(" suffix=")" suffixOverrides=",">
                <if test="user.id!=null and user.id!=''">id,</if>
                <if test="user.name!=null and user.name!=''">name,</if>
                <if test="user.pswd!=null and user.pswd!=''">pswd</if>
            </trim>
            <trim prefix="values(" suffix=");" suffixOverrides=",">
                <if test="user.id!=null and user.id!=''">#{user.id},</if>
                <if test="user.name!=null and user.name!=''">#{user.name},</if>
                <if test="user.pswd!=null and user.pswd!=''">#{user.pswd}</if>
            </trim>
        </foreach>
    </insert>
    @Test
    public void inBatch() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        User in1 = new User( "in1", "in1");
        User in2 = new User( "in2", "in2");
        List<User> list = Arrays.asList(in1, in2);
        int res = mapper.inBatch(list);
        System.out.println(res);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

5.5 xml文件中sql语句重复部分提炼

<sql id="sel">select * from user</sql>
//将select * from user换成下面这句
<include refid="sel"/>

 六、特殊sql

1.模糊查询

List<User> getUsersByNameLike(@Param("name") String name);
    <!--模糊查询-->
    <!--以下三种可互相替换
    "%"#{name}"%";
    '%${name}%';
    concat('%',#{name},'%');
    -->
    <select id="getUsersByNameLike" resultType="pojo.User" parameterType="java.lang.String">
        <include refid="sel"/>
        where name like
        "%"#{name}"%";
    </select>
    @Test
    public void getUserByNameLike() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> list = mapper.getUsersByNameLike("u");
        System.out.println(list);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

2.批量删除

传入string类型的参数

int delMore(@Param("ids") String ids);
    <delete id="delMore" parameterType="java.lang.String">
        delete
        from user
        where id in(${ids});
    </delete>
    @Test
    public void delMore() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        System.out.println(mapper.delMore("12,13"));
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

3.获取新增数据的自增主键

useGeneratedKeys="true"--->当前sql语句使用了自增主键

keyProperty="id"--->自动递增的主键赋值给映射文件的实体类中的id属性

七、自定义字段映射

在数据库的表中字段为user_name,映射到java文件中的userName,这里只说最简单好用的方法

在MyBatis的全局配置中设置开启数据库下划线自动映射为实体类驼峰(如:emp_name映射为empName)

在多条件查询中的代码上修改,后续也有练习

<settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

/*
* 实体类
* */
@Data//getter、setter方法
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
@ToString
public class User {
    private int id;
    private String userName;
    private String pswd;

    public User(String name, String pswd) {
        this.userName = name;
        this.pswd = pswd;
    }
}

八、mybatis缓存

缓存:本次查询到的数据暂存,下次同一个查询条件下不访问数据库直接从缓存拿,前提是数据表没有被改变

一级缓存:同一个sqlSession查询的

二级缓存:同一个sqlSessionFactory查询的

九、多表查询

emp:员工表

      emp_id  emp_name  emp_sex  dept_id

dept:部门表

      dept_id  dept_name

仅做查询练习

1.实体类设计

/*
* 部门表
* */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Dept {
    private int deptId;
    private String deptName;
    private List<Emp> emps;
}
/*
* 部门表
* */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Emp {
    private int empId;
    private String empName;
    private String empSex;
    private Dept dept;
}

2.查询员工信息包括部门

核心配置文件

<setting name="autoMappingBehavior" value="FULL"/>--->resoultMap是否嵌套都自动映射

Emp getEmpById(@Param("id") int id);
    <resultMap id="emprs" type="pojo.Emp">
        <association property="dept" javaType="pojo.Dept"></association>
    </resultMap>
    <select id="getEmpById" resultMap="emprs" parameterType="int">
        select *
        from emp
                 left join dept on emp.dept_id = dept.dept_id
        where emp_id = #{id};
    </select>
    @Test
    public void selEmp() throws Exception {
        //创建mapper实例
        EmpMapper mapper = session.getMapper(EmpMapper.class);
        System.out.println(mapper.getEmpById(1));
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

3.查询部门下的所有员工

//empmapper
List<Emp> getAllEmpByDeptId(@Param("id") int id);
//deptmapper
Dept getDeptById(@Param("id") int id);
<resultMap id="deptrs" type="pojo.Dept">
        <collection property="emps" column="dept_id" select="mapper.EmpMapper.getAllEmpByDeptId"></collection>
    </resultMap>
    <select id="getDeptById" resultMap="deptrs" parameterType="int">
        select *
        from dept where dept.dept_id=#{id};
    </select>
    @Test
    public void selDept() throws Exception {
        //创建mapper实例
        DeptMapper mapper = session.getMapper(DeptMapper.class);
        System.out.println(mapper.getDeptById(2));
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

十、mybatis注解开发

一般的增删改查,xml文件中不写对于的雨具,但是需要有xml

 一对多

十一、mybatis分页插件

1、pom.xml中导入依赖
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.2.0</version>
</dependency>
2、在MyBatis核心配置文件中配置分页插件(mybatis-config.xml)
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <property name="helperDialect" value="mysql"/>
    </plugin>
</plugins>

pageNum:当前页的页码

pageSize:每页显示的条数

navigatePages:设置导航分页的页码数

@Test
    public void selectAll() throws Exception {
        //创建mapper实例
        UserMapper mapper = session.getMapper(UserMapper.class);
        //在查询操作开始之前开启分页
        PageHelper.startPage(2, 3);
        //执行sql
        List<User> i = mapper.getUsers(new User());
        //在查询获取list集合之后,获取分页相关的数据
        PageInfo<User> pageInfo = new PageInfo<>(i,2);
        System.out.println(pageInfo);
        //提交事务
        session.commit();
        //释放资源
        session.close();
    }

十二、Spring基础入门案例

1.新建Maven工程,导入spring依赖

<!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.1</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>

2.编写User.java

public class User {
    public User(){
        System.out.println("User类中的无参构造方法被调用...");
    }
    public void add(){
        System.out.println("add....");
    }
}

3.编写spring核心配置文件(applicationContext.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">
    <!--
        id:唯一标识
        class:要创建的对象的全类名(包名+类名)
    -->
    <bean id="user" class="com.hait.userTest.User"></bean>
</beans>

4.编写测试类

@Test
    public void testUserOb(){
        //加载spring核心配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取创建对象,使用了User类的无参构造,使用反射创建
        /*
        * 反射:
        * 1.加载核心配置文件
        * 2.对核心配置文件进行解析
        * 3.获取bean标签属性值----id和class属性
        * 4.使用反射根据类的全路径创建对象
        * */
        User user = (User) ac.getBean("user");
        System.out.println("对象地址"+user);
        //使用对象调用方法进行测试
        user.add();
    }

    //反射创建对象
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("com.hait.userTest.User");
        User user = (User) clazz.newInstance();//高版本过时
//        clazz.getDeclaredConstructor().newInstance();---高版本使用这个
        System.out.println("通过反射创建对象:"+user);
    }

5.加上日志框架

<!--日志-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.19.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j2-impl</artifactId>
      <version>2.19.0</version>
    </dependency>

在resources新建log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数(最小是5秒钟)-->
<configuration monitorInterval="5" status="warn">
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->


    <!--变量配置-->
    <Properties>
        <!-- 格式化输出:%date表示日期(可缩写成%d,后同),%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
        <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %highlight{%-5level} [%t] %highlight{%c{1.}.%M(%L)}: %msg%n" />
        <!-- 定义日志存储的路径 -->
        <property name="FILE_PATH" value="log" />
        <!--<property name="FILE_NAME" value="myProject" />-->
    </Properties>

    <!--此节点有三种常见的子节点:Console,RollingFile,File-->
    <appenders>

        <!--console节点用来定义输出到控制台的Appender-->
        <!--target:SYSTEM_OUT或SYSTEM_ERR,一般只设置默认:SYSTEM_OUT-->
        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式,默认为:%m%n,即只输出日志和换行-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
        </console>

        <!--        &lt;!&ndash;文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用&ndash;&gt;-->
        <!--        <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">-->
        <!--            <PatternLayout pattern="${LOG_PATTERN}"/>-->
        <!--        </File>-->


        <!-- 这个会打印出所有的debug及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileDebug" fileName="${FILE_PATH}/debug.log" filePattern="${FILE_PATH}/debug/DEBUG-%d{yyyy-MM-dd}_%i.log.gz">
            <!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <!--如果配置的是“%d{yyyy-MM}”,滚动时间单位就是月。“%d{yyyy-MM-dd}”,滚动时间单位就是天-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <!--指定滚动日志的策略,就是指定新建日志文件的时机-->
            <Policies>
                <!--interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>,modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动-->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="100MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="15">
                <!--删除15天之前的日志-->
                <Delete basePath="${FILE_PATH}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz" />
                    <IfLastModified age="360H" />
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>


        <!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/info/INFO-%d{yyyy-MM-dd}_%i.log.gz">
            <!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>,modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动-->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="100MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="15"/>
        </RollingFile>


        <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/error/ERROR-%d{yyyy-MM-dd}_%i.log.gz">
            <!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>,modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动-->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                <SizeBasedTriggeringPolicy size="100MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="15"/>
        </RollingFile>
        <!--启用异步日志,阻塞队列最大容量为20000,超出队列容量时是否等待日志输出,不等待将直接将日志丢弃-->
        <Async name="Async" bufferSize="20000" blocking="true">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFileDebug"/>
            <AppenderRef ref="RollingFileInfo"/>
            <AppenderRef ref="RollingFileError"/>
        </Async>
    </appenders>


    <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
    <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="info" additivity="false">
            <AppenderRef ref="Async"/>
        </logger>
        <!--监控系统信息-->
        <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
        <Logger name="org.springframework" level="info" additivity="false">
            <AppenderRef ref="Async"/>
        </Logger>
        <!--root 节点用来指定项目的根日志,level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.-->
        <root level="debug">
            <AppenderRef ref="Async" />
        </root>
    </loggers>


</configuration>

十三、IoC控制反转

Spring通过IoC容器管理所有java对象的实例化和初始化,控制对象与对象之间的依赖关系。

我们将IoC管理的Java对象成为Spring Bean,它与使用关键字new创建的Java对象没有任何区别。

是一种思想,不是一种技术。

依赖注入:1.setter注入2.构造器注入

十四、基于xml管理bean

在user类中添加两个属性

public class User {
    private String name;
    private Integer age;


    public User(){
        System.out.println("User类中的无参构造方法被调用...");
    }
    public void add(){
        System.out.println("add....");
    }
}

1.获取bean的方式

1.1 根据id获取

1.2 根据类型获取

两个bean的id不同但是class的值是同一个的话会报NoUniqueBeanDefinitionException

1.3 根据id+类型获取

1.4 class的值能否是接口

该接口有只有一个实现类的话,可以。

2.setter注入

public class Student {
    private int age;
    private String name;

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student() {
    }

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("student有参构造被执行....");
    }
}

新建setterIn.xml文件,仅仅是为了区分,标准的核心配置文件名是applicationContext.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">
    <!--1.setter注入-调用的是实体类中的setter方法
        name:属性名
        value:属性值
        ref:属性值为对象而非普通文本
    -->
    <bean id="student" class="com.hait.pojo.Student">
        <property name="name" value="张三"/>
        <property name="age" value="18"/>
     </bean>
</beans>

3.构造器注入

    <!--2.构造器注入-->
    <bean id="student" class="com.hait.pojo.Student">
        <constructor-arg name="name" value="zhangsan"/>
        <constructor-arg name="age" value="22"/>
     </bean>

4.特殊值的处理

4.1 字面量赋值

<property name="name" value="张三"/>

4.2 null值

int类型不可以赋空值

<property name="age">
    <null></null>
</property>

4.3 xml实体

<property name="name" value="&lt;&gt;"/>

 4.4 CDATA节

<![CDATA[内容]]>

<property name="name">
   <value><![CDATA[a<b]]></value>
</property>

5.特殊类型属性的注入

按下图设计实体类

测试类中仅使用以下代码 

@Test
    public void getTest(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("exam1.xml");
        Teacher tea = (Teacher) ac.getBean("bean的id");
        System.out.println(tea);
    }

5.1 对象类型属性注入

5.1.1 外部bean注入
<bean id="cla" class="com.hait.pojo.MyClass"/>
<bean id="tea" class="com.hait.pojo.Teacher">
    <property name="myClass" ref="cla"/>
</bean>

5.1.2 内部bean注入
    <!--外部bean注入-->
    <bean id="tea" class="com.hait.pojo.Teacher">
        <property name="myClass">
            <bean id="cls" class="com.hait.pojo.MyClass"/>
        </property>
    </bean>

5.1.3 级联属性赋值
    <!--级联属性赋值-->
    <bean id="cls1" class="com.hait.pojo.MyClass">
        <property name="name" value="1班"/>
    </bean>
    <bean id="tea" class="com.hait.pojo.Teacher">
        <property name="myClass" ref="cls1"/>
        <property name="myClass.name" value="2班"/>
    </bean>

5.2 数组类型注入

    <!--数组类型注入-->
    <bean id="tea4" class="com.hait.pojo.Teacher">
        <property name="myClass" ref="cls1"/>
        <property name="vacation">
            <array>
                <value>周三</value>
                <value>周五</value>
                <value>周日</value>
            </array>
        </property>
    </bean>

5.3 集合类型注入

5.3.1 list集合

准备工作:

    <bean id="stu1" class="com.hait.pojo.Student">
        <property name="name" value="张三"/>
        <property name="age" value="22"/>
    </bean>
    <bean id="stu2" class="com.hait.pojo.Student">
        <property name="name" value="李四"/>
        <property name="age" value="12"/>
    </bean>
    <bean id="stu3" class="com.hait.pojo.Student">
        <property name="name" value="王五"/>
        <property name="age" value="32"/>
    </bean>

方法1:

    <!--list集合注入-->
    <util:list id="stuList">
        <ref bean="stu1"/>
        <ref bean="stu2"/>
        <ref bean="stu3"/>
    </util:list>
    <bean id="tea5" class="com.hait.pojo.Teacher">
        <property name="myClass" ref="cls1"/>
        <property name="students" ref="stuList"/>
        <property name="vacation">
            <array>
                <value>周三</value>
                <value>周五</value>
                <value>周日</value>
            </array>
        </property>
    </bean>

方法2:

<bean id="tea6" class="com.hait.pojo.Teacher">
        <property name="myClass" ref="cls1"/>
        <property name="students">
            <list>
                <ref bean="stu1"/>
                <ref bean="stu2"/>
                <ref bean="stu3"/>
            </list>
        </property>
        <property name="vacation">
            <array>
                <value>周三</value>
                <value>周五</value>
                <value>周日</value>
            </array>
        </property>
    </bean>

5.3.2 map集合

方法1:

    <util:list id="stuList">
        <ref bean="stu1"/>
        <ref bean="stu2"/>
        <ref bean="stu3"/>
    </util:list>
    <util:map id="scores">
        <entry key="数学" value="90"/>
        <entry key="英语" value="80"/>
        <entry key="语文" value="70"/>
    </util:map>
    <bean id="tea5" class="com.hait.pojo.Teacher">
        <property name="myClass" ref="cls1"/>
        <!--list集合-->
        <property name="students" ref="stuList"/>
        <!--map集合-->
        <property name="score" ref="scores"/>
        <!--数组-->
        <property name="vacation">
            <array>
                <value>周三</value>
                <value>周五</value>
                <value>周日</value>
            </array>
        </property>
    </bean>

方法2:

    <bean id="tea6" class="com.hait.pojo.Teacher">
        <property name="myClass" ref="cls1"/>
        <!--list集合-->
        <property name="students">
            <list>
                <ref bean="stu1"/>
                <ref bean="stu2"/>
                <ref bean="stu3"/>
            </list>
        </property>
        <!--map集合-->
        <property name="score">
            <map>
                <entry key="数学" value="90"/>
                <entry key="英语" value="80"/>
                <entry key="语文" value="70"/>
            </map>
        </property>
        <!--数组-->
        <property name="vacation">
            <array>
                <value>周三</value>
                <value>周五</value>
                <value>周日</value>
            </array>
        </property>
    </bean>

如果List集合中要传入的类型为String这样的类型

     <util:list id="pos">
        <value>东</value>
        <value>西</value>
        <value>南</value>
        <value>北</value>
    </util:list>
.....
<property name="position" ref="pos"/>

如果map集合传入的是Student类型等

    <util:map id="stus">
        <entry key-ref="stu1" value-ref="cls1"/>
        <entry key-ref="stu2" value-ref="cla"/>
    </util:map>
    <bean id="tea7" class="com.hait.pojo.Teacher">
        <property name="stus" ref="stus"/>
    </bean>

5.4 引入外部文件注入

依赖

    <!--数据库-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.30</version>
    </dependency>
    <!--数据源-->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.10.1</version>
    </dependency>

数据库文件

db.user=root
db.password=root
db.url=jdbc:mysql://localhost:3306/student?serverTimezone=UTC
db.driver=com.mysql.cj.jdbc.Driver

 spring核心配置文件

<?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">

    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${db.user}"/>
        <property name="password" value="${db.password}"/>
        <property name="jdbcUrl" value="${db.url}"/>
        <property name="driverClass" value="${db.driver}"/>
    </bean>
</beans>

 测试

@Test
    public void getJdbc() throws SQLException, PropertyVetoException {
        ApplicationContext ac = new ClassPathXmlApplicationContext("配置文件名");
        DataSource source = ac.getBean(ComboPooledDataSource.class);
        Connection connection = source.getConnection();
        System.out.println(connection);
    }

 6.基于xml的自动装配

环境准备:三层架构, Controller调用service,service调用dao

首先在userServiceImpl中创建userDao类型的属性并创建setter方法,在addService方法中调用userDao中的addDao方法

其次在controller中创建service类型的属性并创建setter方法,在controlller中调用service中的方法

最后创建测试类进行测试 

//userDao
public interface UserDao {
    void addDao();
}
//userDaoImpl
public class UserDaoImpl implements UserDao {
    @Override
    public void addDao() {
        System.out.println("userDao中的方法执行了...");
    }
}
//userService
public interface UserService {
    void addService();
}
//userServiceImpl
public class UserServiceImpl implements UserService {
    //1.创建userDao类型的属性,并生成set方法
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void addService() {
        System.out.println("addService中的方法执行了...");
        /*原生写法*/
        /*UserDao userDao = new UserDaoImpl();
        userDao.addDao();*/

        /*注入后调用dao中的方法*/
        userDao.addDao();
    }
}
//UserController
public class UserController {
    //2.定义service类型的属性并生成set方法
    private UserService userService;
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void addUser(){
        System.out.println("controller中的方法执行了...");
        /*原生写法*/
        /*UserService userService = new UserServiceImpl();
        userService.addService();*/

        /*经过注入,调用service的方法*/
        userService.addService();
    }
}
//Test
    @Test
    public void autoBean(){
        ApplicationContext ac = new ClassPathXmlApplicationContext(
                "bean-auto.xml");
        UserController userController = ac.getBean(
                "userController", UserController.class);
        userController.addUser();
    }
//bean-auto.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--1.创建三个对象
    2.bean标签中的autowire属性:autowire="byType"根据类型注入,byName:根据名称注入
    -->
    <bean id="userController" class="com.hait.controller.UserController" autowire="byType"/>
    <bean id="userService" class="com.hait.service.impl.UserServiceImpl" autowire="byType"/>
    <bean id="userDao" class="com.hait.dao.impl.UserDaoImpl"/>
</beans>

十五、基于注解的方式进行bean管理

注解是代码中的一种特殊标记,格式:@注解名称(属性1=属性值,...)

可以简化xml配置

实际开发中一般用的都是注解

步骤:

1.引入依赖(前面都引入过了)

2.开启组件扫描

        spring默认不使用注解装配bean,因此我们需要再spring的xml配置中,通过context:component-scan元素开启自动扫描功能。开启功能后,spring会自动扫描指定的包及其子包下单所有类,如果类上使用了@Component注解,就将该类装配到容器中。

3.使用注解定义bean,下述四个注解功能都是一样的

        @Component:描述spring中的bean,可以使用在任何层次

        @Repository:一般用于数据访问层(Dao)

        @Service:一般用于业务层(Service)

        @Controller:一般用于控制层(Controller)

4.依赖注入

        @AutoWired:默认是byType

<?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">

    <!--开启组件扫描,要扫描的包名写的越具体越好,因为越具体扫描花费的时间越少-->
    <!--1.最基本的写法-->
    <context:component-scan base-package="com.hait"/>

    <!--2.指定要排除扫描的组件
            use-default-filters="true“(默认),所设置的包下所有的类都需要扫描,此时可以使用排除扫描
            use-default-filters="false“,所设置的包下所有的类都不扫描,此时可以使用包含扫描
    -->
    <context:component-scan base-package="com.hait">
        <!--整合springmvc时,controller由mvc扫描,不需要spring扫描-->
        <!--1.根据注解排除-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--2.根据类型排除(全类名)-->
        <!--<context:exclude-filter type="assignable" expression="com.hait.controller.UserController"/>-->
    </context:component-scan>

    <!--3.仅扫描制定组件-->
    <context:component-scan base-package="com.hait" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--<context:include-filter type="assignable" expression="com.hait.controller.UserController"/>-->
    </context:component-scan>
</beans>

1.Autowired 

1.1 属性注入

1.2 setter注入

    private UserService userService;
    //第二种方式:setter注入,其余部分同理
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

1.3 构造方法注入

    private UserService userService;
    //第三种方式:构造方法注入,其余部分同理
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

1.4 形参上注入

    private UserService userService;
    public UserController(@Autowired UserService userService) {
        this.userService = userService;
    }

如果属性有且仅有一个有参构造函数,那么可以省略注解

    private UserService userService;
    public UserController(UserService userService) {
        this.userService = userService;
    }

1.5 @Autowired+@Qualifier类型+名称注解

若dao层有两个实现类,那么仅仅使用Autowired注解就会报错

解决办法

2.@Resource

高于jdk11或低于jdk8的都需要引入依赖

默认根据名称注入(byName),未指定name时,使用属性名作为name。通过name找不到的话会自动启动byType注入。

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

 2.1 根据名称

2.2 不指定名称则根据属性名进行注入

十六、spring全注解开发

使用一个配置类取代配置文件

package com.hait.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration //配置类
@ComponentScan("com.hait") //开启注解扫描
public class SpringConfig {

}

在测试类中测试

    @Test
    public void autoBean(){
//        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //加载配置类
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserController userController = ac.getBean(UserController.class);
        userController.addController();
    }

spring剩下的:

Spring整合JUnit5

SpringAOP

Spring事务

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尢词

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值