Spring给Bean注入

给Bean属性赋值(注入)

1. 通过有参构造方法设置
2. 设置注入(set方法)

设置注入(set方法)

属性:基本数据类型/String

value标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//第一种:
<bean id="peo" class="com.bjsxt.pojo.People">
<property name="id" value="222"></property>
<property name="name" value="zhangsan"></property>
</bean>

//第二种:
<bean id="peo" class="com.bjsxt.pojo.People">
<property name="id">
<value>222</value>
</property>

<property name="name">
<value>zhangsan</value>
</property>
</bean>

属性:Set<?>

set标签 – value标签

1
2
3
4
5
6
7
<property name="set">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>

属性:List<?>

list标签 – value标签

1
2
3
4
5
6
7
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>

属性:数组

array标签 – value标签

1
2
3
4
5
6
7
<property name="strs">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
</array>
</property>

属性:map

map标签 – entry标签(key value属性)

1
2
3
4
5
6
<property name="map">
<map>
<entry key="a" value="b"></entry>
<entry key="c" value="d"></entry>
</map>
</property>

属性:properties

pros标签 – prop标签(key属性)

1
2
3
4
5
6
<property name="demo">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
</props>
</property>

DI (依赖注入)

Dependency Injection:类A依赖类B对象,把B赋值给A的过程就叫做依赖注入

DI和Ioc其实是一样的!!!(Ioc是将创建对象的步骤交给spring去做)

1
2
3
4
5
6
7
8
<bean id="peo" class="com.bjsxt.pojo.People">
<property name="desk" ref="desk"></property> //ref是可以跳转到bean里面id叫做desk的bean
</bean>

<bean id="desk" class="com.bjsxt.pojo.Desktop">
<property name="id" value="1"></property>
<property name="price" value="77"></property>
</bean>

Spring

Spring概述

Rod Johnson提出轮子理论:不用重复发明轮子(直接使用写好的代码)

  • Spring核心功能

    1. IoC/DI    控制反转/依赖注入
    2. AOP       面向切面编程
    3. 声明式事务

框架分析

框架图(八个部分)

具体讲解

Test

test:spring提供测试功能

Core Container

1. Beans:创建类对象并管理对象
2. Core:核心类
3. Context:上下文参数 获取外部资源/管理注解
4. spEl:expression.jar

AOP

AOP:实现aop功能需要依赖

Aspects

Aspects:切面AOP依赖的包

Instrumentation

Messaging

Data Access / Integration

1. JDBC: spring对于JDBC封装后的代码
2. ORM:封装持久层框架的代码(ssh里面的Hibernate)
3. transactions:对应spring-tx.jar -- 声明式事务使用

Web

spring完成web相关功能
例:tomcat加载spring配置文件时需要sping-web包

spring容器

1. 容器(Container):Spring当作一个大容器
2. ApplicationContext接口(老版本的BeanFactory接口)的子接口
3. Spring3之后将sping框架的功能拆分为多个jar

Ioc 控制反转(Inversion of Control)

将原来要new实例化对象 –> 交给spring完成

  1. 控制: 控制类的对象

  2. 反转: 交给spring负责

  3. Ioc最大作用:解耦


Spring环境搭建

导入jar

新建applicationContext.xml配置文件

关于配置文件的知识点:

1
2
3
4
1. Spring配置文件信息内容 --> Spring容器ApplicationContext
2. Spring配置文件基于schema(文件扩展名.xsd)
3. schema是DTD升级版
4. Spring配置文件引入一个xsd就有一个namespace(xmlns就是去找相关文档位置)

具体写法:

1
2
3
4
5
6
7
8
9
10
11
12

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

<!-- id 表示获取到对象标识 class 创建哪个类的对象 -->
<bean id="peo" class="com.bjsxt.pojo.People"/> // bean标签去创建对象 id用来之后getBean中第一个参数调用 class是写具体类的全路径

</beans>

编写实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

public class People {
private int id;
private String name;

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;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + "]";
}
}

编写测试类

分析使用

1. 对比getBean()和getBeanDefinitionNames()方法
     getBean()方法两个参数:
        第一个:配置文件中bean标签id值
        第二个:返回值类型(默认Object)         
     getBeanDefinitionNames() Spring容器中目前所有管理的所有对象

2. 要使用ApplicationContext容器 -- 我们暂时用ClassPathXmlApplicationContext去获取资源

具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
public static void main(String[] args) {

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = ac.getBean("peo",People.class);
System.out.println(people);

String[] names = ac.getBeanDefinitionNames();
for (String string : names)
{
System.out.println(string);
}

}
}

Spring创建对象的三种方式

1. 构造方法创建
     无参构造创建:默认
     有参构造创建:需要明确配置

2. 实例工厂

3. 静态工厂

构造方法创建(bean标签更改)

实体类创建好无参构造方法和有参构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public People(){
super();
System.out.println("执行无参构造方法");
}

public People(int id,String name){
super();
this.id=id;
this.name=name;
System.out.println("执行有参构造方法1");
}

public People(String name,int id){
super();
this.id=id;
this.name=name;
System.out.println("执行有参构造方法2");
}

无参构造方法

1
<bean id="peo" class="com.bjsxt.pojo.People"/>   //直接简单的写id和class即可

有参构造方法(constructor-arg标签)

四个属性(可以区别用哪个有参构造方法 默认是用最下面的!!!!)

index:参数索引(0开始)
value:参数对应值
name:参数名
type:区别关键字和封装类(int和Integer)
1
2
3
4
<bean id="peo" class="com.bjsxt.pojo.People"> 
<constructor-arg index="0" name="id" type="int" value="123"></constructor-arg>
<constructor-arg index="1" name="name" type="java.lang.String" value="zhangsan"></constructor-arg>
</bean>

实例工厂(先工厂后对象)#

生成一个实例工厂

1
2
3
4
5
public class PeopleFactory{
public People newInstance(){ //一般都叫newInstance()
return new People(1,"测试");
}
}

配置文件配置工厂对象

1
2
3
4
5
6
7
// 原来代码格式:
PeopleFactory factory=new PeopleFactory()
People P1=factory.newInstance();

<bean id="factory" class="com.bjsxt.pojo.PeopleFactory"></bean> //用了后面类创建了一个工厂对象叫factory

<bean id="p1" factory-bean="factory" factory-method="newInstance"></bean> //用上面的factory工厂对象调用newInstance方法 返回为p1

静态工厂(快速创建对象)

不需要工厂(静态方法直接用)

1
2
3
4
5
public class PeopleFactory{
public static newInstance(){ //一般都叫newInstance() static静态!!!!
return new People(1,"测试");
}
}

配置文件调用方法

1
2
3
4
// 原来代码格式:
People P2=PeopleFactory.newInstance();

<bean id="p2" class="com.bjsxt.pojo.PeopleFactory" factory-method="newInstance"></bean> //直接调用静态newInstance方法

Mybatis运行原理总结

Mybatis运行原理

运行过程中涉及的类

1. Resources Mybatis中的IO流的工具类 : 加载配置文件
2. SqlSesssionFactoryBuilder()构建器 :创建SqlSessionFactory接口的实体类
3. XMLConfigBuilder() : Mybatis全局配置文件内容构造器类 --读取流内容并转为JAVA代码
4. Configuration: 封装全局配置文件所有内容 
5. DefaultSqlSessionFactory():是SqlSessionFactory()接口实现类
6. Transaction:事务类 -- 每一个sqlssion都有一个transaction对象
7. TransactionFactory:事务工厂
8. Executor: Mybatis执行器
9. SimpleExecutor: 默认执行器
10. BatchExcutor:批量操作
11. openSession:参数控制:
12. DefaultSqlSession:SqlSession接口实现类
13. ExcptionFactory:异常工厂

流程图

文字描述

1. Mybatis执行时先要通过Resources加载全局配置文件
2. 通过实例化SqlSessionFactoryBuilder构建器 -- 帮助SqlSessionFactory接口实现类DefaultSqlSessionFactory
3. 用XmlConfiguration解析全局配置文件 
4. 将解析结果给Configuration --> 最后又给了DefaultSqlSessionFactory

----

5. 由SqlSessionFactory工厂创建SqlSession
6. 每次创建SqlSession都必须要要用TransactionFactory创建Transaction对象
7. 有了事务对象之后就需要有Excutor执行器
8. 创建实例化DefaultSqlSession传给SqlSession接口
9. 进行不同的JDBC
10. 成功就提交 --关闭
11. 不成功就回滚事务

Mybatis注解

注解(简化配置文件)

Mybatis的注解简化mapper.xml文件(涉及动态SQL就不可用(×))

注解和全局配置文件mapper.xml共存!!!

注解的简单实用

使用注解:
        1. package标签(用接口里面写注解)
        2. mapper标签里面用class属性(原来是resource取对应配置文件)

例:
    1. 第一种用package的方式:    
     <mappers>
        <package name="com.bjsxt.com"/>  //因为后面的被对应的配置文件用别名起了
    </mappers>

    2. 第二种更改class属性

    <mappers>
        <mapper class="com.bjsxt.com.XXXMapper"/>
    </mappers>

package(接口内写注解)

1. 查询 @Select

1
2
@Select("select * from teacher")
List<Teacher> selAll();

2. 新增 @Insert

1
2
@Insert("insert into teacher values(default,#{name})" )
int insTeacher(Teacherteacher);

3. 修改 @Update

1
2
@Update("update teacher set name=#{name} where id=#{id}" )
int upd Teacher(Teacherteacher);

4. 刪除 @Delete

1
2
@Delete("delete from teacher whereid=#{0}" )
int delById(intid);

注解实现resultMap功能(老师和学生的例子)

其实就是一些注解名和resultMap标签对等

学生接口添加注解

1
2
@Select("select * from student wheret id=#{0}")  //相当于student配置文件里面写sql语句
List<Student> selByTid(int tid);

老师接口添加注解

1
2
3
4
5
6
7
8
9
@Results(       //相当于resultMap标签
value={
@Result(id=true,property="id",column="id"), //相当于id/result标签
@Result(property="name",column="name"),
@Result(property="list",column="id",many=@Many(select="com.bjsxt.mapper.StudentMapper.selByTid")) //Many相当于collection(集合对象)
})

@Select("select * from teacher")
List<Teacher> selTeacher();

总结

1.     @Results()   == resultMap标签
2.     @Result()    == id/result标签 (主键/其他键)
3. @Result(id=true) == id标签
4.      @Many()     == collection标签 (集合对象)
5.      @One()      == association标签 (单个对象)

使用Mybatis的动态Sql实现多表查询

具体实现(student项目)

创建数据库

1
2
3
4
5
6
7
8
9
10
11
create table teacher(
id int(10) primary key auto_increment,
name varchar(20)
);

create table student(
id int(10) primary key auto_increment,
name varchar(20),
age int(3),
tid int(10)
);

数据库情况:

学生表添加外键:

搭建环境

1. 导入相关jar包
2. 准备mybatis.xml全局配置文件(里面利用package标签找那个接口!!!!)
3. 准备student实体类
4. 准备teacher实体类
5. 准备pageInfo分页实体类
6. 准备实现类接口StudentMapper
...

Mybatis实现多表查询方式

多表查询三种方式

1. 业务装配:
    两表单表查询 -- 在业务(service)将查询结果关联
2. 通过Auto Mapping特性
    两表联合查询 -- 通过别名完成映射    
3. 使用Mybatis的resultMap标签进行实现

类中(其他类) 分类

1. 单个对象

2. 集合对象

单表resultMap

resultMap标签(mapper.xml中)

程序员控制sql查询结果与实体类的映射关系
默认:Mybatis使用Auto Mapping特性(resultType属性)
更改:Mybatis使用resultMap属性引用resultMap标签(不写resultType属性)

具体操作

1. 数据库(id和name两列):

2. 实体类(我们用id1和name1区别)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Teacher {
private int id1;
private String name1;

public int getId1() {
return id1;
}
public void setId1(int id1) {
this.id1 = id1;
}
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}

}

3. 在TeacherMapper.xml配置文件中使用resultMap标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<mapper namespace="com.bjsxt.mapper.TeacherMapper">

<resultMap type="teacher" id="mymap">
<!-- 主键用id -->
<id column="id" property="id1"/>
<!-- 其他列用result -->
<result column="name" property="name1"/>
</resultMap>

<select id="selAll" resultMap="mymap">
select * from teacher
</select>

</mapper>

单表总结使用

1. 实体类去写需要映射的名称(id和name 实体类就写id1和name1)
2. 配置文件中select里面把resultType改成使用resultMap属性 
    注: resultMap属性值 == resultMap标签的id值
3. 书写resultMap标签
    注: resultMap两个属性一个是类型 一个是和select里面属性匹配的id
         主键使用id标签 其他列用result标签
         里面column写的是数据库的名称 property写的是映射的实体类名称

resultMap实现关联单个对象(N+1方式) association标签

就是先查询出一个表的全部信息 然后根据这个表的信息再查另外一个表的信息(两个表合并)

具体操作

1. 学生数据库的tid是刚才老师id的外键

2. 学生实体类除了自己的属性还要有一个老师的对象

1
2
3
4
5
6
 //只列举了变量
private int id;
private String name;
private int age;
private int tid;
private Teacher teacher; //老师类的对象!!!!!!

3. 学生配置文件(通过association标签把tid给老师的sql语句中当做id)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<mapper namespace="com.bjsxt.mapper.StudentMapper">

<resultMap type="student" id="linahe">

<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="tid" property="tid"/>
<association property="teacher" select="com.bjsxt.com.TeacherMapper.selById" column="tid"></association>

</resultMap>

<select id="selAll" resultMap="lianhe">
select * from student
</select>

</mapper>

4. 老师配置文件(只写根据id查老师信息的sql语句)

1
2
3
4
5
6
7
<mapper namespace="com.bjsxt.mapper.TeacherMapper">

<select id="selById" resultType="teacher" parameterType="int"> //只需要写好根据id查老师的sql操作
select * from teacher where id=#{id}
</select>

</mapper>

结果分析

图例分析流程:

具体实现过程:

1. 准备老师和学生类(要有老师类对象)
2. 准备老师的配置文件(通过id查询结果)
3. 准备学生的配置文件
    3.1 先写自己的sql语句 -- resultMap属性连接到resultMap标签的id  -- id标签写学生的主键映射 result标签写学生的其他列映射
    3.2 一定要用association标签!!!(column属性把学生的tid拿过来 select去掉老师配置文件的sql语句的方法名一定是全路径!!)

resultMap实现关联集合对象(N+1方式) colloction标签

其实关联 集合对象(老师返回学生的list集合) / 单个对象(学生传老师一个对象) 只是从不同角度来看!!!!!!

具体操作

1. teacher实体类(放的就是list集合)

1
2
3
private int id;
private String name;
private List<Student> list; //list集合返回结果

2. student配置文件(只需要写简单的sql语句让老师传过来id当tid用)

1
2
3
4
5
6
7
<mapper namespace="com.bjsxt.mapper.StudentMapper">

<select id="selByTid" resultType="student" parameterType="int">
select * from student where tid=#{id}
</select>

</mapper>

3. teacher老师配置文件(通过collection标签将id传过去当tid查)

1
2
3
4
5
6
7
8
9
10
11
12
13
<mapper namespace="com.bjsxt.mapper.TeacherMapper">

<resultMap type="teacher" id="mymap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="list" ofType="student" select="com.bjsxt.mapper.StudentMapper.selByTid" column="id"></collection>
</resultMap>

<select id="selAll" resultMap="mymap">
select * from teacher
</select>

</mapper>

结果分析

图例分析流程:

具体实现过程:

1. 准备老师类(要有list集合返回学生类信息)和学生类
2. 准备学生的配置文件(只需要sql语句通过id查所有信息)
3. 准备老师的配置文件
    3.1 通过查询的sql语句去找resultMap标签 然后标签去找学生配置文件的方法查处结果(将id传过去当tid用)

多表resultMap加载集合对象联合查询方式

假设老师1有多个学生(数据库会一下子很多行) – 我们现在让老师1 后面跟学生(减少重复每次都要出现老师1)

具体操作

1. teacher实体类(放的就是list集合)

1
2
3
private int id;
private String name;
private List<Student> list; //list集合返回结果

2. 只在teacher配置文件改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<mapper namespace="com.bjsxt.mapper.TeacherMapper">
<resultMap type="teacher" id="mymap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="list" select="com.bjsxt.mapper.StudentMapper.selByTid" column="id"></collection>
</resultMap>

<select id="selAll" resultMap="mymap">
select * from teacher
</select>

<resultMap type="teacher" id="mymap1">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
<collection property="list" ofType="student" >
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="age" property="age"/>
<result column="tid" property="tid"/>
</collection>
</resultMap>

<select id="selAll1" resultMap="mymap1">
select t.id tid,t.name tname,s.id sid,s.name sname,age,tid from teacher t LEFT JOIN student s on t.id=s.tid;
</select>

</mapper>

结果分析

图例分析流程:

具体实现过程:

1. 准备老师类(要有list集合返回学生类信息)和学生类
2. 准备学生的配置文件(只需要sql语句通过id查所有信息)
3. 准备老师的配置文件
    3.1 通过查询的sql语句去找resultMap标签 然后标签去找学生配置文件的方法查处结果(将id传过去当tid用)
    3.2 因为他返回的结果我需要一个老师对应很多学生 -- 所以我们要再写一个resultMap标签去映射list(一行一行给) --最终通过这个标签返回答案

AutoMapping加载单个对象 ( 添加反单引号 )

使用多表联合查询(起别名!!)

具体操作

1. 学生实体类(老师类对象)

1
2
3
4
5
6
 //只列举了变量
private int id;
private String name;
private int age;
private int tid;
private Teacher teacher; //老师类的对象!!!!!!

2. teacher配置文件(一个是student)

1
2
3
4
5
6
<mapper namespace="com.bjsxt.mapper.TeacherMapper">
<select id="selAll" resultType="teacher">
select t.id id,t.name name,s.id `list.id`,s.name `list.name`,age `list.age`,tid `list.tid`
from teacher t LEFT JOIN student s on t.id=s.tid //展示的是list集合输出
</select>
</mapper>

3. student配置文件(里面通过老师对象(反单引号) teacher.id等传过来用)

1
2
3
4
5
6
7

<mapper namespace="com.bjsxt.mapper.StudentMapper">
<select id="selAll" resultType="student">
select t.id `teacher.id`,t.name `teacher.name`,s.id id,s.name name,age,tid
from student s LEFT JOIN teacher t on t.id=s.tid //里面通过老师对象(反单引号) teacher.id等传过来用)
</select>
</mapper>

Mybatis缓存

缓存概述

提升运行效率(让应用程序减少对数据库的访问)


默认SqlSession缓存开启

1
2
3
4
5
1. 一旦你创建select标签 就会有一个对应statement对象

2. 同一个SqlSession对象调用同一个select --> 只有第一次访问数据库(后面都是将查询结果缓存到SqlSession缓存区)

3. 有效范围: 必须是同一个SqlSession对象(多个sqlsession对象就会执行多次!!)

SqlSessionFactory 二级缓存

引入原因

//问题概述:
    以前要是写两个sql语句两个sqlsession对象 --就会有两个缓存区域 --然后执行就会有两次执行(效率低)

//使用二次缓存:
    让两个sqlsession是获取同一个factory --就只有一个大的单独的缓存区域 -- 就只有一次执行

使用注意事项

1. 有效范围: 
     就是同一个factory的所有SqlSession都可以获取

2. 使用范围
     主要用于数据频繁使用但是很少修改

3. 使用步骤
     只需要在mapper.xml的select标签中添加
            <cache readOnly="true"></cache>

4. 当SqlSession对象进行close() / commit()  --> sqlsession缓存的数据刷  --> SqlSessionFactory缓存区

缓存流程


ThreadLocal

ThreadLocal

线程容器,给线程绑定一个Object内容,只要线程不变就可以随时取出

改变线程 –> 无法(×)取出内容

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test {
public static void main(String[] args) {
//使用ThreadLocal类
final ThreadLocal<String> threadLocal=new ThreadLocal<>(); //final不让实例化
threadLocal.set("测试");

//创建子线程
new Thread() {
public void run() //匿名内部类
{
String result = threadLocal.get();
System.out.println("结果"+result);
};
}.start();

String result = threadLocal.get();
System.out.println(result);

}
}

优化线程


动态SQL

动态SQL

根据不同的条件执行不同的SQL语句

Mybatis中动态SQL在mapper.xml里面添加逻辑判断

前期准备:
        1. 准备好之前getMapper接口绑定和参数传递的环境

if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

//接口需要写方法
List<Log> selByAccinAccout(@Param("accout") String accout,@Param("accin") String accin);

//配置xml文件
<select id="selByAccinAccout" resultType="log">
select * from log where 1=1 //if是需要写where1=1

<!-- OGNL表达式 直接写key / 对象的属性 不需要添加任何特定字符号 -->
<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>

<if test="accout!=null and accout!=''">
and accout=#{accout}
</if>
</select>

where (比if在sql少写where 1=1)

先去掉前面的and 然后加where (先去后加)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

//接口需要写方法
List<Log> selByAccinAccout(@Param("accout") String accout,@Param("accin") String accin);

<select id="selByAccinAccout" resultType="log">
select * from log //省去了if情况要写的where 1=1

<where>
<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>

<if test="accout!=null and accout!=''">
and accout=#{accout}
</if>
</where>

</select>

choose when otherwise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

//接口需要写方法
List<Log> selByAccinAccout(@Param("accout") String accout,@Param("accin") String accin);

<select id="selByAccinAccout" resultType="log">
select * from log
<!-- OGNL表达式 直接写key / 对象的属性 不需要添加任何特定字符号 -->

<where>
<choose>
<when test="accin!=null and accin!=''"> //其实相当于将if改成了when
and accin=#{accin}
</when>
<when test="accout!=null and accout!=''">
and accout=#{accout}
</when>
</choose>
</where>

</select>

set 修改sqlset从句

去掉最后一个逗号 如果set里面有内容就会生成set关键字 (先去后加)

1
2
3
4
凑出形式: 
update log
set id=?,accin=?,accout=?, (最后一个逗号会被set删除掉 )
where id=?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

//接口写方法
int upd(Log log);

//配置xml里面

<update id="upd" parameterType="log">

update log
<set>
id=#{id},
<if test="accin!=null and accin!=''">
accin=#{accin},
</if>

<if test="accout!=null and accout!=''">
accout=#{accout},
</if>
</set>
where id=#{id}

</update>

//测试类使用接口产生getMapper对象 --然后创建log对象 set添加值
LogMapper logMapper = session.getMapper(LogMapper.class);
Log log=new Log();
log.setId(1);
log.setAccIn(accin); //上面输入
log.setAccOut(accout); //上面输入
int index=logMapper.upd(log); //获得结果

//提交
session.commit(); //一定要记得提交!!! 更新呀
session.close();
System.out.println("程序执行结束");

trim 可以去除和添加

trim属性介绍

1
2
3
4
prefix 在前面添加内容(+)
prefixOverrides 去掉前面内容(-)
suffix 在后面添加内容(+)
suffixOverrides 去掉后面内容(-)

模拟其他功能

先删除and 后添加where (模拟where功能)

1
2
3
4
凑出形式: 
select *
from log
where accin=? //先删除and 然后添加where
1
2
3
4
5
6
7

<select id="selByLog" parameterType="log" resultType="log">
select * from log
<trim prefix="where" prefixOverrides="and">
and accin={accin}
</trim>
</select>

先删除逗号 后添加set (模拟set功能)

1
2
3
4
凑出形式: 
update log
set id=?,accin=?,accout=?, (最后一个逗号会被set删除掉 )
where id=?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<update id="upd" parameterType="log">
update log
<trim prefix="sex" suffixOverrides=,"">
id=#{id},
<if test="accin!=null and accin!=''">
accin=#{accin},
</if>

<if test="accout!=null and accout!=''">
accout=#{accout},
</if>
</trim>
where id={id}
</update>

bind 重新赋值 / 模糊查询

模糊查询
原内容前/后添加内容

1
2
3
4
<select id="selByLog" parameterType="log">
<bind name="accin" value="'%'+accin+'%'">
#{money}
</select>

foreach

循环参数内容 **
**内容前后添加内容

添加分隔符

属性介绍

1. collection 要遍历的集合
2. item 迭代变量 
      #{迭代变量名}获取内容
3. open 循环后左边添加内容
4. close 循环后右边添加内容
5. separator 每层循环时 元素之间的分隔符

在in查询

1
2
3
4
凑出来:
select *
from log
where id in (1,2,3);
1
2
3
4
5
6
<select id="selIn" parameterType="list" resultType="list">
select * from log where id in

<foreach collection="list" item="abc" open="(" close=")" separator=",">
#{abc}
</select>

批量新增 (效率低)

1. 写sql语句批量新增:

1
2
3
4
凑出来:
insert
into log
values (default,1,2,3),(default,12,2,3),(default,1,22,3)

2. openSession()必须指定

1
factory.openSession(ExecutorType.BATCH);  //底层的PreparedStatement.addBatch();

sql + include 多表查询

多表查询 (sql片段复用)

*将mysql这个表然后内容是四个属性 上面select可以直接include调用 *

1
2
3
4
5
6
7
8
<select id="">
select <include refid="mysql"></include> //直接include的refid标签调用mysql表
from log
</select>

<sql id="mysql">
id,accin,accout,money //给mysql这个表添加一个id 内容是四个属性
</sql>

getMapper接口绑定和多参数传递

Mybatisi接口绑定 + 参数传递

mybatis和spring整合使用的方案

实现步骤:

1.创建接口
    要求:
         1.1 接口包名 == mapper.xml的namespace标签 (接口和配置xml文件在同一个包)
         1.2 接口方法名 == mapper.xml的id属性  (接口名和配置xml里面的id名一样)
2.mybatis.xml全局配置文件中:
    mappers标签里面 -- 使用package标签

举例实现

1. 准备数据库
2. 准备jar包
3. 准备全局mybatis.xml文件
4. 准备实体类 Log
5. 准备mapper包 
    5.1 准备接口 LogMapper
    5.2 准备配置xml文件 LogMapper.xml
6. 准备测试类 test

代码结构层次

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Log {
private int id;
private String accIn;
private String accOut;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccIn() {
return accIn;
}
public void setAccIn(String accIn) {
this.accIn = accIn;
}
public String getAccOut() {
return accOut;
}
public void setAccOut(String accOut) {
this.accOut = accOut;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}

@Override
public String toString() {
return "Log [id=" + id + ", accIn=" + accIn + ", accOut=" + accOut + ", money=" + money + "]";
}

}

全局配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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="logImpl" value="LOG4J"/>
</settings>

<typeAliases>
<package name="com.bjsxt.pojo" />
</typeAliases>

<!-- default引用environment的id,当前所使用的环境 -->
<environments default="default">
<!-- 声明可以使用的环境 -->
<environment id="default">
<!-- 使用原生JDBC事务 -->
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="njdxrjgc7777777."/>
</dataSource>
</environment>
</environments>

<mappers>
<package name="com.bjsxt.mapper"/>
</mappers>

</configuration>

LogMapper接口

1
2
3
4
5
public interface LogMapper {
List<Log> selAll(); //方法名是selAll

List<Log> selByAccInAccount(String accin,String accout); //多参数
}

LogMapper.xml配置文件(sql语句)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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="com.bjsxt.mapper.LogMapper">

<select id="selAll" resultType="log"> <!-- 方法名和接口方法一致 resultYType使用别名 -->
select * from log
</select>

<select id=" selByAccInAccount" resultType="log"> <!-- 多参数不写parameterType -->
select * from log where accin=#{0} and accout=#{1}
</select>

</mapper>

测试代码类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Test {
public static void main(String[] args) throws IOException {
//固定三行
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();

// 使用JDK的动态代理设计模式 面向接口的代理设计模式(必须有接口)
LogMapper logMapper = session.getMapper(LogMapper.class); //给接口产生实例化 接口 -- 实例化proxy -- 反射到xml文件
List<Log> list = logMapper.selAll();
for(Log log1:list) {
System.out.println(log1);
}

List<Log> list2 = logMapper.selByAccInAccount("1","7");
for(Log log2:list2) {
System.out.println(log2);
}

session.close();
System.out.println("程序执行结束");

}
}

多参数传递

1
2
3
4
5
6
7
8
9
10
11
12
	1. 配置文件中写sql语句和id  -- (因为id要和接口方法一致) -- 创建接口方法
sql语句中accin 和 accout写法
第一种: #{0} #{1} 调用方法: "1" "7"
第二种: #{param1} #{param2} 调用方法: "1" "7"
第三种(通过map的实现思路) #{accin} #{accout} 调用方法: @param("accin") @param("accout")

2. 然后测试类调用


```

## 总结 ##
1. 其实就是我们把配置文件的id(sql语句实现的方法)和接口一样 然后通过接口去实例化proxy代理,然后代理反射到xml文件内实现。

2. 之所以可以实例化是因为我们使用其中一种动态代理设计模式  面向接口

    LogMapper logMapper = session.getMapper(LogMapper.class);   //方法要接口的类加载器 调用getMapper方法
        List<Log> list = logMapper.selAll();  //实例化对象获得结果

```


Mybatis实现转账

前期准备

数据库准备

在ssm数据库下通过查询建立account表

导入jar包

准备全局配置文件mybatis.xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

<?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="logImpl" value="LOG4J"/>
</settings>

<typeAliases>
<package name="com.bjsxt.pojo"/> <!-- 起别名 方便在配置的xml里面直接返回值就可以只写类名-->
</typeAliases>

<environments default="default">
<environment id="default">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="njdxrjgc7777777."/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="com/bjsxt/mapper/AccountMapper.xml"/> <!-- 直接调用配置文件 执行sql语句 -->
</mappers>

</configuration>

准备pojo包的实体类Account

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

public class Account {
private int id;
private String accNo;
private int password;
private String name;
private double balance;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccNo() {
return accNo;
}
public void setAccNo(String accNo) {
this.accNo = accNo;
}
public int getPassword() {
return password;
}
public void setPassword(int password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}

准备mapper包下的AccountMapper.xml文件

通过分析我们要有三个任务:分别是写在三个select标签下完成对应任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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="com.bjsxt.mapper.AccountMapper">
<!-- 根据帐号和密码查询账户信息 -->
<select id="selByAccnoPwd" resultType="account" parameterType="account"> //id就是此方法名称 resultType就是返回值类型
select * from account where accno=#{accNo} and password=#{password}
</select>

<!-- 根据帐号和姓名查询账户信息 -->
<select id="selByAccnoName" resultType="account" parameterType="account">
select * from account where accno=#{accNo} and name=#{name}
</select>

<!-- 根据accNo修改账户余额 -->
<update id="updBalanceByAccno" parameterType="account">
update account set balance=balance+#{balance} where accno=#{accNo}
</update>

</mapper>

准备serive包下的AccountService接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface AccountService {

//帐号和密码不匹配状态码
int ACCOUNT_PASSWORD_NOT_MATCH=1;

//余额不足
int ACCOUNT_BALANCE_NOT_ENOUGH=2;
//账户姓名不匹配
int ACCOUNT_NAME_NOT_MATCH=3;
//转账失败
int ERROR=4;
//转账成功
int SUCCESS=5;

//转账功能
int transfer(Account accIn,Account accOut) throws IOException;

}

准备1.0版本的serviceimpl包

准备思路:

1. 先判断账号和密码是否匹配 (调用方法查sql语句)
    2. 然后判断是否有足够转账金额 (判断账号密码查信息返回给account类 然后调用balance去判断是否足够)
        3. 判断收款人账号和名字是否正确 
            4. 然后进行转账交易 (调用方法 一个减少一个增加)
                5. 判断是不是成功
                    5.1 成功就session.commit()提交 --  session.close()关闭  -- 返回成功的结果值
                    5.2 失败就session.rollback()回滚 --session.close()关闭 -- 返回失败的结果值 

实现类实现初级1.0事务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

public class AccountServiceImpl implements AccountService {
@Override
public int transfer(Account accIn, Account accOut) throws IOException {

//固定的三行生产出session
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();

//先判断帐号和密码是否匹配
Account accOutSelect = session.selectOne("com.bjsxt.mapper.AccountMapper.selByAccnoPwd",accOut); //根据账号和密码查询
if(accOutSelect!=null){ //账号和密码匹配
if(accOutSelect.getBalance()>=accOut.getBalance()) { //余额够
Account accInSelect = session.selectOne("com.bjsxt.mapper.AccountMapper.selByAccnoName",accIn); //根据账号和姓名查询
if(accInSelect!=null) {
accOut.setBalance(-accOut.getBalance()); //set设置一下为负数
int index=session.update("com.bjsxt.mapper.AccountMapper.updBalanceByAccno",accOut); //如果传的是accOut 就需要的是扣除交易额
index += session.update("com.bjsxt.mapper.AccountMapper.updBalanceByAccno",accIn); //转账过去
if(index==2) {
session.commit(); //成功就提交
session.close();
return SUCCESS;
}else {
session.rollback(); //失败就要回滚
session.close();
return ERROR;
}
}else {
return ACCOUNT_NAME_NOT_MATCH; //账号和姓名不匹配
}
}else {
return ACCOUNT_BALANCE_NOT_ENOUGH; //余额不足
}
}else{
return ACCOUNT_PASSWORD_NOT_MATCH; // 账号和密码 不匹配
}

}
}

准备servlet包下的TransferServlet类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

@WebServlet("/transfer")
public class TransferServlet extends HttpServlet {

//面向接口编程
private AccountService accService = new AccountServiceImpl();

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//需要使用到中文
req.setCharacterEncoding("utf-8");

//获取转账人的信息
Account accOut = new Account();
accOut.setAccNo(req.getParameter("accOutAccNo"));
accOut.setPassword(Integer.parseInt(req.getParameter("accOutPassword")));
accOut.setBalance(Double.parseDouble(req.getParameter("accOutBalance")));

//获取收款人信息
Account accIn =new Account();
accIn.setAccNo(req.getParameter("accInAccNo"));
accIn.setName(req.getParameter("accInName"));

//通过面向接口编程 调用转账功能
int index = accService.transfer(accIn, accOut);

if(index==AccountService.SUCCESS) //转账成功的返回值和 service的静态success对比
{
resp.sendRedirect("/bank/show"); //成功跳转到展示页面
}
else
{
HttpSession session = req.getSession();
session.setAttribute("code", index); // 获得状态码
resp.sendRedirect("/bank/error/error.jsp"); //新建的error文件下的error.jsp页面
}

}
}

准备登陆/失败/转账查询的页面

log显示成功界面

1
2
3
<body>
成功的log.jsp
</body>

index主页面界面

1
2
3
4
5
6
7
8
9
10
11
12
<body>

<form action="transfer" method="post"> //写一个页表 -- servlet类
转账账户:<input type="text" name="accOutAccNo"/><br/>
密码:<input type="password" name="accOutPassword"/><br/>
金额:<input type="text" name="accOutBalance"/><br/>
收款帐号:<input type="text" name="accInAccNo"/><br/>
收款姓名:<input type="text" name="accInName"/><br/>
<input type="submit" value="转账"/>
</form>

</body>

error错误界面

1
2
3
4
5
<body>
对不起操作失败:<br/>
错误原因:
${sessionScope.code} //通过jsp方式传出错误的原因对应的service的数字
</body>

准备log4j (查错)

带入jar包和配置文件log4j.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
log4j.rootCategory=ERROR, CONSOLE ,LOGFILE   //显示设置error去查找错误

log4j.logger.com.bjsxt.mapper=DEBUG //给这个包添加log4j文件

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C %d{YYYY-MM-dd hh:mm:ss} %m %n

log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=E:/my.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%m %n

全局配置文件中配置log4j

1
2
3
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>

执行结果


日志记录

创建表log

1
2
3
4
5
6
create table log(
id int(10) primary key auto_increment,
accout varchar(18),
accin varchar(8),
money double
);

新增log实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Log {
private int id;
private String accIn;
private String accOut;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccIn() {
return accIn;
}
public void setAccIn(String accIn) {
this.accIn = accIn;
}
public String getAccOut() {
return accOut;
}
public void setAccOut(String accOut) {
this.accOut = accOut;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}

新增关于log表的配置xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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="com.bjsxt.mapper.LogMapper">

<insert id="insLog" parameterType="log">
insert into log values(default,#{accOut},#{accIn},#{money}) //添加数据
</insert>

<select id="selByPage" parameterType="map" resultType="log"> //分页
select * from log limit #{pageStart},#{pageSize}
</select>

<select id="selCount" resultType="long"> //查询所有
select count(*) from log
</select>

</mapper>

在serviceimpl实现类添加

1
2
3
4
5
6
7
8

//在已经转账成功 index==2之后添加

Log log=new Log();
log.setAccIn(accIn.getAccNo()); //取出来所有信息然后添加到log实体类对象
log.setAccOut(accOut.getAccNo());
log.setMoney(accIn.getBalance());
session.insert("com.bjsxt.mapper.LogMapper.insLog",log); //转账成功就添加到log表里面

日志文件显示转账信息(log4j)

1
2
3
4
5
6
//1. 要在log4j配置文件内更改:
log4j.appender.LOGFILE.layout.ConversionPattern=%m %n //最后要是%m %n

//2. 在刚才的实现类代码下添加日志文件记录(同时将log4j第一行的异常给一个info才可以显示)
Logger logger=Logger.getLogger(AccountServiceImpl.class);
logger.info(log.getAccOut()+"给"+log.getAccOut()+"在"+new Date().toLocaleString()+"转了"+log.getMoney()); //在log4j的五种异常中选info异常

分页展示功能

mapper包xml里面添加分页功能的sql语句

1
2
3
4
5
6
7
<select id="selByPage" parameterType="map" resultType="log">  //分页
select * from log limit #{pageStart},#{pageSize}
</select>

<select id="selCount" resultType="long"> //查询所有
select count(*) from log
</select>

添加分页显示的实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class PageInfo {
private int pageSize;
private int pageNumber;
private long total;
private List<?> list;
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageNumber() {
return pageNumber;
}
public void setPageNumber(int pageNumber) {
this.pageNumber = pageNumber;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}

}

service层接口实现方法

1
2
3
4
5
6
7
8
9
public interface LogService  {
/**
* 分页显示
* @param pageSize
* @param pageNumber
* @return
*/
PageInfo showPage(int pageSize,int pageNumber) throws IOException;
}

service实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

public class LogServiceImpl implements LogService {

@Override
public PageInfo showPage(int pageSize, int pageNumber) throws IOException {

//固定三行
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();

Map<String,Object> param = new HashMap<>();
param.put("pageStart",pageSize*(pageNumber-1)); //获取当前页要从第几个开始
param.put("pageSize", pageSize); //获取一页展示几个


List<Log> list = session.selectList("com.bjsxt.mapper.LogMapper.selByPage",param); //param是一个map 创建一个map 将最后的map集合的值给log实体类
long count = session.selectOne("com.bjsxt.mapper.LogMapper.selCount"); //查询总数

PageInfo pi = new PageInfo(); //分页类实现对象(四个属性)
pi.setList(list);
pi.setPageNumber(pageNumber);
pi.setPageSize(pageSize);
pi.setTotal(count%pageSize==0?count/pageSize:count/pageSize+1); //算出来总共几个几页

return pi;

}
}

准备servlet类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

@WebServlet("/show")
public class ShowServlet extends HttpServlet {
private LogService logService = new LogServiceImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

int pageSize = 2;
String pageSizeStr = req.getParameter("pageSize"); //获取一页有几个
if(pageSizeStr!=null&&!pageSizeStr.equals("")){
pageSize = Integer.parseInt(pageSizeStr); //强转
}
int pageNumber = 1;
String pageNumberStr = req.getParameter("pageNumber"); //获取有几页
if(pageNumberStr!=null&&!pageNumberStr.equals("")){
pageNumber = Integer.parseInt(pageNumberStr); //强转
}

//最后跳转
req.setAttribute("pageinfo", logService.showPage(pageSize, pageNumber));
req.getRequestDispatcher("/log.jsp").forward(req, resp); //跳转

}
}

书写log.jsp页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<table border="1">
<tr>
<th>转账帐号</th>
<th>收款帐号</th>
<th>转账金额</th>
</tr>
<c:forEach items="${pageinfo.list}" var="log">
<tr>
<td>${log.accOut }</td>
<td>${log.accIn }</td>
<td>${log.money }</td>
</tr>
</c:forEach>
</table>
<a href="show?pageSize=${pageinfo.pageSize }&pageNumber=${pageinfo.pageNumber-1}" <c:if test="${pageinfo.pageNumber<=1 }"> onclick="javascript:return false;"</c:if>>上一页</a>
<a href="show?pageSize=${pageinfo.pageSize }&pageNumber=${pageinfo.pageNumber+1}" <c:if test="${pageinfo.pageNumber>=pageinfo.total }"> onclick="javascript:return false;"</c:if>>下一页</a>
</body>
</html>

全局配置文件添加mappers

1
2
3
4
<mappers>
<mapper resource="com/bjsxt/mapper/AccountMapper.xml"/> <!-- 直接调用配置文件 执行sql语句 -->
<mapper resource="com/bjsxt/mapper/LogMapper.xml"/> <!-- 直接调用配置文件 执行sql语句 -->
</mappers>

总结

最终代码结构:

最终结果:


,