Fork me on GitHub

白鹿原观后感

白鹿原观后感

说是观后感,其实是读后感。我阅读了白鹿原的原著,并没有看白鹿原电视剧。但是在阅读原著时,在我脑海中勾画出的画面使我折服。我很喜欢这本书,故事情节有趣,情节推进很快也是有历史感的。

对白鹿原中一些事的看法

白鹿原中描写了很多事,很多事是在现在人看来是幼稚的,无聊的,但是“人不能跳过他的历史局限性来评论他。”因此也是合理的。现代人不了解的。

看完白鹿原后的感受

看完白鹿原后,我对自己的历史的欠缺感到懊悔,我应该多读一些书籍来了解那个时代,那个变换莫测的时代,肯定不是一句两句话就能概括的。

文革到底是什么样的

文革到底是什么样,我没经历过,电视剧不敢拍。因此需要阅读很多书籍来了解来完善那个时代。

如《兄弟》等余华作者的笔下,红卫兵们是对个人的迫害,我当时看时到觉得不以为然,只是为误会一个好人感到惋惜,只当他们是疯子。

但是看到《白鹿原》中,红卫兵和“造反派”们甚至产生了武力冲突,活力冲突。在《白鹿原》中,作者将他们的行为视为“夺权”。“红卫兵”们占领了县级以上的权利,而“造反派”们在农村搞破坏。

《白鹿原》中描写到了“红小将”们的“革命”。他们所谓的“破四旧”,打砸孔子塑像,甚至到挖掉朱先生坟墓的地步。正如朱先生生前的预知“天作孽,尚可存。人作孽,不可活”以及“还要闹到什么时候。”

这些在大方向上的描写使我对那段历史产生兴趣,万幸这个作家好像写了很多这方面的内容,我可以看一下。

鬼神论

在《白鹿原》中,在“田小娥附身”以及“判官抓鬼”和“新妻遇鬼”这些地方由所谓鬼神的描写。

当时看到“田小娥附身后”询问母亲是否真的有此等事,没想到当年真的在她的娘家的那个村庄发生了附身的事。对于鬼神我是不信的,但是身边竟然真的出现了这种事,增加了我对这方面的兴趣,激发我解释这种现象的兴趣。在我看来,这种附身的人有几种特点:“有别人的记忆”,“声调会变”,“时而清醒时而糊涂”。在我询问过身边人后,发现每个村庄多多少少都会发生这种事,也都有所谓的“仙”来收走他们。

但是在《平凡的世界》中的所谓的“仙”,都是在极度无能的情况下来混口饭吃的人假装的,和《树先生》一样。

作家的不同描写激发了我的阅读兴趣。

对于“鬼神”我个人是不信服的,我认为一定是一种物理现象,这种现象一定有科学解释,只是我的学识不够,在以后在阅读更多来了解这些事。

革命?

在白鹿原中,共有两次革命,一次是农革,一次是起义。

农革时,由各地的党员委派几名“先进”的农民到西安上了为时一个月的教育,然后他们再到各乡镇去教育其他农人进行革命。

矛盾在于,这些被委派去的农人在当时人的眼里都是“死皮狗”等等,事实上他们后来的举动确实让人大跌眼镜。

第二次是起义

几个为就党守门的军官竟然一瞬间就抛弃原来的政府进行“起义”,他们只是墙头草,是两边派。他们的革命性是十分低的,但是这种人竟然在“起义”后进入统治阶级,他们运用新宪法对原来的投机派进行党争。

原本是国民党狗腿子的白孝文竟然成了县长,只是因为这个投机派首先给党写邀功信,这种人注定是蛀虫。还堂而皇之的说自己的工作是革命工作。

原本是农协分子的黑娃,先是入伍,后当了土匪,后来又进了保安团,最后起义成了“副县长”,最后被白孝文通过新法给判了死刑。

这些虚假的投机派竟然在占据革命的成果,我相信是没来得及对他们进行清算。

只是当地最顶端的权利别调换了,但是那些人还是那些人,在审问黑娃时甚至没有做过多的“求证”。

这就是所谓的“革命”?所谓的“起义”难道就是简单的夺权?

我们真正的革命战士

我们真正的革命战士哪里去了?

我能记住的书中真正的战士有“鹿兆鹏”、“白灵”、“韩裁缝”以及“鹿兆海”。

首先讲讲“鹿兆海”,他不是共产党,但是他是真正的军人,在中门山痛击日军,但是却死于与“剿共匪”。作者在这里揭示了蒋介石的虚伪面孔,自己的嫡系武装装备到牙齿却到西安“吃粮”,而将地方军视为“杂牌军”,却把最重要的战事最紧的关口留给他们守。在他们屡次胜利后竟把他们调离,让他们和共产党互杀,毕竟蒋介石所谓的“安内”也包括他们。

“鹿兆鹏”和“韩裁缝”都是真正的共产党人,在党最困难的时候都坚持了下去,他们最后都不知道结局。

“白灵”是十分可惜的,她在我们的根据地的一次所谓的“抓出内奸”在我看来是活生生的“党挣”下死于活埋。当时她的孩子尙小。

真正的战士,他们最终却因为种种原因牺牲,不知去向。活着的“投机分子”却最后苟活得到权利,多么的讽刺。

更换证件照背景(简单不稳定)

更换证件照背景(简单不稳定)

某天一个高中同学拜托我帮她改变证件照的背景,但是当时我不会PS,虽然想到了下边这个程序(虽然现在看来是不行的),我因为懒就没有帮助她,现在我来介绍我的程序的解决方式。

程序原理

程序原理:

  • 通过改变图片的像素块的颜色改变图片的背景

  • 图片看似是整个一片,但是其实是由一个个像素块拼接而来的

    整个图片

    色素快

  • 获得一个个像素点的rgb值,然后修改这个值,就完成了背景的修改

实践

代码

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
package com.dwx;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

public class ChangeColor {
public static void main(String[] args) throws FileNotFoundException {
//读取照片
File file = new File("src/main/java/com/dwx/pic.jpg");
//新图片地址
File file1 = new File("src/main/java/newpic.jpg");
FileOutputStream fileOutputStream = new FileOutputStream(file1);
//通过idea的图像功能获取到的图片的背景的RGB颜色
Color colorOld = new Color(253,253,255);
//希望改成的RGB颜色
Color colorNew = new Color(250, 5, 5);
BufferedImage read = null;
try {
read = ImageIO.read(file);
int height = read.getHeight();
int width = read.getWidth();
for (int i=0;i<width;i++){
for(int j=0;j<height;j++){
if (read.getRGB(i,j)==colorOld.getRGB()){
//如果相等就将次点的颜色设置成我们需要的颜色
read.setRGB(i,j,colorNew.getRGB());
}
}
}
//最后 把修改过的RGB再写回去
ImageIO.write(read,"jpg",fileOutputStream);
} catch (IOException e) {
e.printStackTrace();
}


}
}

代码步奏:

  • 读取照片File()
  • 通过Image类的read()方法来读取这个图片中的数据 (假设产生的对象为read)
  • 通过read的getHeight()方法获取图片的高
  • 通过read的getWidth()方法获取图片的宽
  • 通过一个for循环遍历图片的一个个像素点的并通过getRGB()方法获取到像素点的RGB值
  • 如果该店的RGB值和我们想要换掉的值一样,那么通过setRGB()方法来设置该点的颜色
  • 通过ImageIo的write()方法,把更改过得read在创建成一个新的图片

成品:

成品

局限性

很明显这个图片有个白边 有的地方没有被修改

原因:

  • 一个图片的背景不可能是纯色的,每个像素点的RGB可能都不一样
  • 不同颜色之间有一个渐变,渐变是由很多不同的色素快构成的,因此无法改变边缘的颜色不同的问题

mybatis实现复杂查询

mybatis实现复杂查询

实现复杂查询的环境配置

我们需要准备的东西:

  • 两个带有相联结的数据库表格(以student和teacher为例)
  • 创建一个带有日志的使用lambok插件的优化配置后的java项目

两个数据库表格的准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, 秦老师);

CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, 小明, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, 小红, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, 小张, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, 小李, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, 小王, 1);

在执行sql时注意:不能直接执行玩全部的sql,因为可能在执行插入操作前,还没有将表格建好。

java项目的准备

  • 导入lambok包(直接放到父项目的xml中,这样每个子项目都能直接使用了)

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    </dependency>
  • 设置日志(在子项目的核心配置文件中设置最简单的日志)

    1
    2
    3
    4
    <!--这里设置了一个最基础的日志-->
    <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
  • 编写剩余的java程序(pojo,until等)

需要注意的点在于:

  • 这一次我么使用了两个实体类,因此为了体现分离的原则,我们把Mapper.xml创建到resource文件夹下,但是要求1.mapper.xml也有相同的包结构 2.mapper.xml与其对应的抽象类同名

    文件位置关系

  • 创建好的每一个xml都需要在核心配置文件中进行配置

    1
    2
    3
    4
    <mappers>
    <mapper resource="com/dwx/mapper/TeacherMapper.xml"/>
    <mapper resource="com/dwx/mapper/StudentMapper.xml"/>
    </mappers>

解释上述为何要相同的包结构:因为在生成target文件时,由于两者有相同的包结构 就会被当成是在一个包下,这就符合了我们之前要求的xml文件与接口类在同一包下且同名的要求

target文件结构

处理多对一问题

处理多对一问题即:从多个表中查寻相关联的数据。

处理方法在MySQL中有两种:

  • 子查询
  • 联表查询

因此在java程序中也出现两种方法:

  • 按照查询嵌套处理
  • 按照结果嵌套处理

按照查询嵌套处理

按照查询嵌套处理的逻辑等同于mysql中的子查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--第一种使用子查询 基本原理 在查询到tid后再查询tname-->

<select id="getStudent_Teacher" resultMap="studentTeacherMap">
select * from mybatis.student1
</select>
<resultMap id="studentTeacherMap" type="Student">
<!--对于基本属性直接进行映射即可-->
<result property="id" column="id"/>
<result property="name" column="id"/>
<!--但是对于引用参数 需要使用assocation来操作-->
<!--这里是嵌套一个方法-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from mybatis.teacher where id = #{tid}
</select>

注意点:

  • 对于<resultmap>,如果是基本类型,直接使用映射即可
  • 如果是引用类型使用<association>
  • 如果是集合类型则使用<collection>

原理就是在每一次查询到tid时到teacher表中查询teacher的名字

用SQL表现为:

1
2
SELECT student1.`id`,student1.`name` ,(SELECT teacher.`name` WHERE teacher.`id` = student1.`tid`) AS teachername
FROM student1,teacher

按照结果嵌套处理

使用这种方法进行处理相当于sql中的联表查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--使用联表查询-->
<select id="getStudent_Teacher2" resultMap="studentTeachermap">
<!--下边是使用链表查询的sql-->
select s.id sid,s.name sname,t.name tname
from student1 s,teacher t
where s.tid = t.id
</select>
<!--西边是链表查询的resultmap-->
<resultMap id="studentTeachermap" type="Student">
<result column="sid" property="id"/>
<result column="sname" property="name"/>
<association property="teacher" javaType="Teacher">
<result column="tname" property="name"/>
</association>
</resultMap>

注意:

  • 这里我们使用了大量的别名 因此在映射时,数据库一边的参数用别名表示
1
2
3
SELECT s.id sid,s.name sname,t.name tname
FROM student1 s,teacher t
WHERE s.tid = t.id

处理一对多问题

环境准备:一对多,一个老师对应多个学生,因此老师的参数有一个是一个一student为类型的集合

而学生参数变为和数据库中参数一样。

student类

1
2
3
4
5
6
7
8
9
10
11
//编写Student实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
//这里是一个联表 在java代码中 直接把链表的参数放进去
private int tid;
}

teacher类

1
2
3
4
5
6
7
8
9
10
//编写Teacher的实体类
//这里直接使用注解来完成实体类的完善
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private String name;
private int id;
private List<Student> studentList;
}

注意:此时由于teacher类中使用了List<Student>因此在SQLresultmap中有所改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<mapper namespace="com.dwx.mapper.TeacherMapper">
<select id="getTeacher" resultMap="teacherMap">
select s.id sid,s.name sname,t.name tname,t.id tid
from mybatis.teacher t, mybatis.student1 s
where s.tid = t.id
</select>
<resultMap id="teacherMap" type="Teacher">
<result property="id" column="id"/>
<result property="name" column="name"/>
<collection property="studentList" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="stid"/>
</collection>
</resultMap>
</mapper>

注意:使用<collection property="java中的属性" foType="list的类型"></collection>这样来给List集合做映射。

Lombok插件的使用

Lombok插件的使用

Lombok插件能够方便pojo类的编写(实体类的编写)

使用Lombok插件的使用可以代替(get/set方法、构造器、toString、hashcode等的编写)

Lombok插件的安装

安装步骤:

  1. 在IDEA中安装Lombok插件:(Setting->plugins->insert…)

    插件安装位置

  2. 导入Lombok的Jar包(project Lombok)[删除<scope></scope>]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    </dependency>

    </dependencies>
  3. 使用Lombok

使用Lombok

在以前 我们都是使用Alt+Ins来方便编写get\set方法等等

以前的实体类

但现在 我们仅仅使用@注解就能完成这个工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.dwx.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//创建与数据库映射的类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class student {
private int id;
private String name;
private String password;

}

现在的编写方法

注解的解释:

  • @Data:代替get/set方法、无参构造、toString、hashcode、equals
  • @AllArgsConstructor:代替有钱构造
  • @NoArgsConstructor:代替无参构造

这个插件还有很多的注解 但是最重要的只有以上三个

mybatis使用注解开发

mybatis使用注解开发

在对接口就行实现时,我们既可以使用xml文件进行配置,也可以使用注解也进行配置。

使用注解进行配置,操作简单,但是功能也简单,复杂的操作还得使用xml配置来实现

使用注解实现查询

使用注解实现查询的底层逻辑是反射

使用注解进行查询与使用xml进行配置除了没有实现的mapper.xml文件外其他的都一致

**文件结构: **

文件结构

少了StudentMapper,xml文件

接口代码

1
2
3
4
5
6
7
8
9

public interface StudentMapper {

//测试使用注解来实现查询
@Select("select * from mybatis.student")
List<student> getStudentList();

}

此时的接口直接在抽象方法上使用注解@Select并且在()里编写SQL语句

核心配置文件代码:

1
2
3
<mappers>
<mapper class="com.dwx.mapper.StudentMapper"/>
</mappers>

虽然没有了xml,但是还是需要进行配置,这里使用的参数是class自然对应我们接口类的全路径

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class test {
@Test
public void getStudentList(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<student> studentList = mapper.getStudentList();
for (student student : studentList) {
System.out.println(student.toString());
}
sqlSession.close();
}
}

测试代码和使用xml时一模一样 没有任何改变。

自动提交事务

之前我们使用的方法提交事务的方法是手动提交事务:

until文件中的代码:

1
sqlSessionFactory.openSession();

测试类中的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void InsertStudnet(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
//获得了sqlSession就需要进行联结获得mapper
UserDao mapper = sqlSession.getMapper(UserDao.class);
//通过mapper对象来进行操作
mapper.InsertStudent(new student(4,"王五","123456"));
//对于需要对数据库进行改动的如:“增删改” 都系要提交事务
sqlSession.commit();//此代码就是提交事务
//关闭sqlsession
sqlSession.close();
}

但是现在 我们在开始SQLsession时就直接设置自动提交事务

1
sqlsessionFactory.openSession(true);

此时就不需要sqlsession.commit(),每一条语句都会自动提交 但是如果sql出错还是会提交 会出现错误

使用注解实现有参查询

实现基础:@Param("名字")注解的使用

在参数前使用@Param("名字")这个注解,然后在@Select(“sql”)中使用#{"名字"}来获取参数。

接口代码:

1
2
3
//测试使用注解实现有参查询
@Select("select * from mybatis.student where id = #{id}")
student getStudentByID(@Param("id") int id);

注意:有几个参数就在几个参数前加@Param("名字")

使用注解实现增加

接口代码:

1
2
3
4
//测试使用注解实现增加
@Insert("insert into mybatis.student (id,name,password) values(#{id},#{name},#{password})")
int InsertStudent(student student);

注意:我们这里的参数是student,是我创建的实体类 也就是引用类,引用类是不需要添加@Params("名字")的,直接使用即可。通过#{"参数名"}就直接获取了应用参数内部包含的参数。

而且此时我们已经设置了自动提交事务,就不用在写sqlsession.commit()了。

使用注解实现删除

接口代码:

1
2
3
//测试使用注解实现删除
@Delete("delete from mybatis.student where id = #{id}")
int DeleteStudentById(@Param("id") int id);

使用注解实现修改

接口代码:

1
2
3
//测试使用注解实现修改
@Update("Update mybatis.student set name = #{name},password = #{password} where id = #{id}")
int UpdateStudentById(@Param("id") int id,@Param("name") String name,@Param("password") String password);

注意:修改sql的书写,有几个参数就在几个参数前加@Param("名字")

@Param("名字")使用的注意事项

  • 有几个参数就在几个参数前加@Param("名字")
  • 基本数据类型以及String加注解,自己创造的实体类(引用数据类型)不用加注解

mybatis实现分页

mybatis实现分页

分页的意义:分页的意义在于减少了数据的处理量

分页可以通过一下的方式实现:

  • sql中的limit实现分页
  • 在java代码中使用RowBounds实现分页

limit实现分页

核心SQL语法:

1
SELECT * FROM 表格名 limit startIndex,pageSize

元素分析:

  • startIndex: 指的是重哪个数据开始查询(默认是从0开始的)
  • pagesize: 指纸张的大小,可以查询到几个元素

回顾mybatis实现一个操作需要的步奏:

  • 编写接口
  • 编写Mapper.xml(主要写sql)
  • 编写测试方法

接口代码:

1
List<student> getStudentListByLimit(Map<String,Object> map);

这里使用的万能的map作为参数

Mapper.xml代码:

1
2
3
<select id="getStudentListByLimit" resultMap="StudentMap" parameterType="map">
select * from mybatis.student limit #{startIndex},#{pageSize}
</select>

有参数的查询必须要规定参数的类型

这里使用的resultMap(结果集映射)作为返回

实现方法代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void getStudentListByLimitTest(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("startIndex",1);
map.put("pageSize",2);
List<student> studentListByLimit = mapper.getStudentListByLimit(map);
for (student student : studentListByLimit) {
System.out.println(student.toString());
}
sqlSession.close();
}

固定格式

RowBounds实现分页

这是更加服了java面向对象特点的方法,没有在sql进行操作,在测试类中进行操作

这种方法已经过时

操作步奏:

  • 接口

    1
    List<student> getStudentByRowBounds();
  • Mapper.xml

    1
    2
    3
    <select id="getStudentByRowBounds" resultMap="StudentMap">
    select * from mybatis.student
    </select>
  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Test
    public void getStudentByRowBounds(){
    MyBatisUtils myBatisUtils = new MyBatisUtils();
    SqlSession sqlSession = myBatisUtils.getSqlSession();
    //其特点就是在sqlsession中直接进行select
    //第三个参数是RowBounds 因此需要创建
    //第一个参数是起始数,第二个参数是页面大小
    RowBounds rowBounds = new RowBounds(0, 3);
    List<student> students = sqlSession.selectList("com.dwx.mapper.StudentMapper.getStudentByRowBounds", null, rowBounds);
    for (student student : students) {
    System.out.println(student.toString());
    }
    }

selectList()方法有三个参数

第一个参数是我们执行这个方法的全路径,第二个数据一般是null,第三个数据是rowBounds

注意:我们这里并没有使用mapper,而是使用selectList,这种方法是已经放弃了的

mybatis日志工厂

mybatis日志工厂

如果一个数据库操作出现了一个异常,我们需要进行排除。日志就是最好的助手。

在以前,我们在程序拍错时使用的是sout获得debug

现在,我们就能够使用日志来进行排错了

日志_MyBatis中文网

日志我们只需要了解两种:STDOUT_LOGGINGLOG4J

STDOUT_LOGGING的使用

STDOUT_LOGGING 的使用十分方便 只需要在核心配置文件(mybatis-config.xml)中配置settings就行

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

配置完就可以直接进行测试

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
Class not found: org.jboss.vfs.VFS
JBoss 6 VFS API is not available in this environment.
Class not found: org.jboss.vfs.VirtualFile
VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
Using VFS adapter org.apache.ibatis.io.DefaultVFS
Find JAR URL: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/pojo
Not a JAR: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/pojo
Reader entry: student.class
Listing file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/pojo
Find JAR URL: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/pojo/student.class
Not a JAR: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/pojo/student.class
Reader entry: ���� < :
Checking to see if class com.dwx.pojo.student matches criteria [is assignable to Object]
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Find JAR URL: file:/E:/java/MyBatisStudy/Mybatis03/target/test-classes/com/dwx/mapper
Not a JAR: file:/E:/java/MyBatisStudy/Mybatis03/target/test-classes/com/dwx/mapper
Reader entry: test.class
Listing file:/E:/java/MyBatisStudy/Mybatis03/target/test-classes/com/dwx/mapper
Find JAR URL: file:/E:/java/MyBatisStudy/Mybatis03/target/test-classes/com/dwx/mapper/test.class
Not a JAR: file:/E:/java/MyBatisStudy/Mybatis03/target/test-classes/com/dwx/mapper/test.class
Reader entry: ���� < U
Find JAR URL: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/mapper
Not a JAR: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/mapper
Reader entry: StudentMapper.class
Reader entry: StudentMapper.xml
Listing file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/mapper
Find JAR URL: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/mapper/StudentMapper.class
Not a JAR: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/mapper/StudentMapper.class
Reader entry: ���� <   com/dwx/mapper/StudentMapper  java/lang/Object getStudentList ()Ljava/util/List; Signature *()Ljava/util/List<Lcom/dwx/pojo/student;>;
Find JAR URL: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/mapper/StudentMapper.xml
Not a JAR: file:/E:/java/MyBatisStudy/Mybatis03/target/classes/com/dwx/mapper/StudentMapper.xml
Reader entry: <?xml version="1.0" encoding="UTF-8" ?>
Checking to see if class com.dwx.mapper.test matches criteria [is assignable to Object]
Checking to see if class com.dwx.mapper.StudentMapper matches criteria [is assignable to Object]
Opening JDBC Connection
Created connection 473153915.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1c33c17b]
==> Preparing: select * from mybatis.student
==> Parameters:
<== Columns: id, name, password
<== Row: 1, 张三, welcome
<== Row: 2, 李四, welcome
<== Row: 4, 王五, 123456
<== Row: 17, dwx, welcome
<== Row: 100, 李一百, welcome
<== Total: 5
student{id=1, name='张三', pwd='welcome'}
student{id=2, name='李四', pwd='welcome'}
student{id=4, name='王五', pwd='123456'}
student{id=17, name='dwx', pwd='welcome'}
student{id=100, name='李一百', pwd='welcome'}

Process finished with exit code 0

这种日志的特点在于:

  • 使用简单 能实现基本功能
  • 只在控制台输出 不可以DIy 不可以控制输出格式

LOG4J的使用

LOG4J应该是使用更加广泛地,但是他的使用需要进行配置,使用起来有点麻烦

LOG4J的使用步骤:

  • 导入LOG4J的依赖
  • 在resource文件下新增一个配置文件(log4j.properties)
  • 编写log4j配置文件(网上搜 不用记)(会在博客中写的)
  • 设置log4j为日志的实现
  • 使用log4j

导入LOG4J的依赖

1
2
3
4
5
6
7
8
<dependencies>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>

在子程序的pom.xml文件中配置

在resource文件下新增一个配置文件(log4j.properties)

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
41
42
43
44
# priority  :debug<info<warn<error
#you cannot specify every priority with different file for log4j
log4j.rootLogger=debug,stdout,info,debug,warn,error

#console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= [%d{yyyy-MM-dd HH:mm:ss a}]:%p %l%m%n
#info log
log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.info.File=./logs/log.log
log4j.appender.info.Append=true
log4j.appender.info.Threshold=INFO
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#debug log
log4j.logger.debug=debug
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.debug.File=./logs/log.log
log4j.appender.debug.Append=true
log4j.appender.debug.Threshold=DEBUG
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#warn log
log4j.logger.warn=warn
log4j.appender.warn=org.apache.log4j.DailyRollingFileAppender
log4j.appender.warn.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.warn.File=./logs/log.log
log4j.appender.warn.Append=true
log4j.appender.warn.Threshold=WARN
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#error
log4j.logger.error=error
log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.error.File =./logs/log.log
log4j.appender.error.Append = true
log4j.appender.error.Threshold = ERROR
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n

设置log4j为日志的实现

在核心配置文件中写

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

使用log4j

使用log4j有两种使用办法:

  • 直接使用
  • 编写使用方法

直接使用

在进行过以上的操作时,直接在操作类中写Logger logger = Logger.getLogger("测试方法类.class")

直接使用即可

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
package com.dwx.mapper;

import com.dwx.pojo.student;
import com.dwx.untils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.List;

public class test {
//注意 此处导包要导Apache的包
Logger logger = Logger.getLogger(test.class);

@Test
public void getStudentListTest(){
//首先需要获取到 mapper
//以下的操作都是固定的 不需要进行任何改变
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<student> studentList = mapper.getStudentList();
for (student student : studentList) {
System.out.println(student.toString());
}

}
}

注意:创建Logger 导包是一定要导Apache log4j的包

在运行后,会产生一个logs文件,里边有log日志

文件的产生

文件中的内容和在控制台中输出的内容一致

文件中的内容

使用测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.dwx.mapper;

import com.dwx.pojo.student;
import com.dwx.untils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.List;

public class test {
//注意 此处导包要导Apache的包
Logger logger = Logger.getLogger(test.class);
@Test
public void log4jTest(){
logger.info("###################infor#################");
logger.debug("##################debug#################");
logger.error("##################error##################");
}
}

这样使用的好处是,在log文件中只会出现我们设置的这几个数据

控制台中的输出

1
2
3
4
com.dwx.mapper.test,log4jTest
[2022-01-11 21:01:04 下午]:INFO com.dwx.mapper.test.log4jTest(test.java:30)###################infor#################
[2022-01-11 21:01:04 下午]:DEBUG com.dwx.mapper.test.log4jTest(test.java:31)##################debug#################
[2022-01-11 21:01:04 下午]:ERROR com.dwx.mapper.test.log4jTest(test.java:32)##################error##################

log.log中的输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2022-01-11 21:01:04 下午 [Thread: main][ Class:com.dwx.mapper.test >> Method: com.dwx.mapper.test.log4jTest(test.java:30) ]
INFO:###################infor#################
2022-01-11 21:01:04 下午 [Thread: main][ Class:com.dwx.mapper.test >> Method: com.dwx.mapper.test.log4jTest(test.java:30) ]
INFO:###################infor#################
2022-01-11 21:01:04 下午 [Thread: main][ Class:com.dwx.mapper.test >> Method: com.dwx.mapper.test.log4jTest(test.java:31) ]
DEBUG:##################debug#################
2022-01-11 21:01:04 下午 [Thread: main][ Class:com.dwx.mapper.test >> Method: com.dwx.mapper.test.log4jTest(test.java:32) ]
ERROR:##################error##################
2022-01-11 21:01:04 下午 [Thread: main][ Class:com.dwx.mapper.test >> Method: com.dwx.mapper.test.log4jTest(test.java:32) ]
ERROR:##################error##################
2022-01-11 21:01:04 下午 [Thread: main][ Class:com.dwx.mapper.test >> Method: com.dwx.mapper.test.log4jTest(test.java:32) ]
ERROR:##################error##################
2022-01-11 21:01:04 下午 [Thread: main][ Class:com.dwx.mapper.test >> Method: com.dwx.mapper.test.log4jTest(test.java:32) ]
ERROR:##################error##################

mybatis结果集映射

mybatis结果集映射

结果集映射(resultType)用来解决我们实体类中的参数名与数据库中列名不一致的问题。

当我们的实体类的参数名与数据库中的列名不一致是 就会发生查询错误

实体类的参数名与数据库中的列名不一致

此时的查询结果

错误的查询结果

我们可以发现 相同的查询正确,但是错误的查询的是null 查询不到

产生错误的原因

1
2
3
4
5
6
7
<select id="getStudentList" resultType="student">
select * from mybatis.student
</select>
<!--这个SQL等共同于-->
<select id="getStudentList" resultType="student">
select id,name,password from mybatis.student
</select>

可以看到 在student里根本没有查询到的password参数。因此产生了错误。

解决方法:

  • 使用别名
  • 结果集映射

使用别名

1
2
3
<select id="getStudentList" resultType="student">
select id,name,password as pwd from mybatis.student
</select>

这样就能直接查询了 但是这种方法是十分基础的,写的代码数量多。

结果集映射(resultType)

使用结果集映射 是在接口类的实现的mapper文件中操作,而不是和我们原来在核心配置文件中操作

1
2
3
4
5
6
7
8
9
10
<mapper namespace="com.dwx.mapper.StudentMapper">
<resultMap id="StudentMap" type="student">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="password" property="pwd"/>
</resultMap>
<select id="getStudentList" resultMap="StudentMap">
select * from mybatis.student
</select>
</mapper>

元素分析:

column:“列”,是指数据库中的字段的列名

property:“属性”,是指实体类中的属性

可以把每个参数都进行映射,也可以只对实体类中的参数与数据库中列名不同的进行映射

mybatis配置解析之映射

mybatis配置解析之映射

介绍:映射(mappers)即,我们之前说的每一个接口的xml文件必须在核心配置文件中“注册”

MapperRegistry:注册绑定我们的Mapper文件

文章源:mappers(映射器)

mybatis映射我们具体使用的有三种方法:

  1. 对xml文件进行映射
  2. 对接口类进行映射
  3. 对接口类所在的包进行映射

对xml文件进行映射

即注册时使用的是Mapper接口文件的实现xml文件

1
2
3
<mappers>
<mapper resource="com/dwx/mapper/StudentMapper.xml"/>
</mappers>

这种映射方式对两个文件的位置没有要求 可以在任何位置创建xml文件

对接口类进行映射

即对接口类进行注册

1
2
3
<mappers>
<mapper class="com.dwx.mapper.StudentMapper"/>
</mappers>

这种映射方式要求:

  • 接口类和我们的实现xml文件(mapper)必须在同一个包下
  • 接口类和我们的实现xml文件(mapper)必须同名

否则就会报错,找不到我们的文件

文件的位置

对接口类所在的包进行映射

1
2
3
<mappers>
<package name="com.dwx.mapper"/>
</mappers>

这种映射方式要求:

  • 接口类和我们的实现xml文件(mapper)必须在同一个包下
  • 接口类和我们的实现xml文件(mapper)必须同名

否则就会报错,找不到我们的文件

文件的位置

mybatis配置解析之别名

mybatis配置之别名

配置_MyBatis中文网

别名

使用别名的意义:能够在xml使用用java中编写的实体类是降低编写代码的冗余性。(全部路径的包名可以不用写了)

实际上就是给java中的实体类编写一个短的名字

使用别名的方法

命名别名可以大致分为两个方法:一、把一个个实体类命名成别名。二、直接引入pojo包 把这个包中的所有实体类都命名成别名;

使用别名的方法:在核心配置文件(mybatis-config.xml)中配置,在这个核心文件中配置过得xml文件中直接使用。

在配置别名时,需要注意的是。这个xml配置文件的标签的使用有先后顺序,不能随意位置放置。

将一个个实体类命名成别名

1
2
3
4
5
6
7
<!--在这里将我们创建的实体类进行别名-->
<!--在核心配置文件中配置别名-->
<!--在下边mapper中注册的xml中就能使用这个别名了-->
<!--这种方法是一下子别名一个实体类-->
<typeAliases>
<typeAlias alias="Student" type="com.dwx.pojo.student"/>
</typeAliases>

上述是xml中的配置

在配置好的xml中可以直接使用:

1
2
3
4
5
<mapper namespace="com.dwx.mapper.StudentMapper">
<select id="getStudentList" resultType="Student">
select * from mybatis.student
</select>
</mapper>

这种方法的特点:

  • 在实体类少时可以使用(方便),但是实体类多了以后就十分麻烦
  • 别名可以DIY 可以在alias后随便设置别名

将实体类的包直接命名成别名

1
2
3
4
<!--也可以直接一下子导入一个实体类的包 这样使用实体类的类名(首字母小写)作为它的别名-->
<typeAliases>
<package name="com.dwx.pojo"/>
</typeAliases>

这种情况下,在配置好的xml直接使用你引入的这个包中的实体类的类名(首字母小写)

1
2
3
4
5
<mapper namespace="com.dwx.mapper.StudentMapper">
<select id="getStudentList" resultType="student">
select * from mybatis.student
</select>
</mapper>

这种方式的特点:

  • 在实体类多时使用十分方便
  • 别名不能DIY——为实体类的类名(首字母小写)

但是说这种方法不能DIY别名是十分不严谨的,如果和注解结合使用就能实现类名的DIY

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
41
42
@Alias("hello")
public class student {
private int id;
private String name;
private String password;

//无参构造
public student() {
}

//有参构造
public student(int id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}

//get和set方法
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 getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

当实体类使用Alias("别名")后,就能在引入这个实体类所在的包后使用这个别名作为别名使用

1
2
3
4
5
<mapper namespace="com.dwx.mapper.StudentMapper">
<select id="getStudentList" resultType="hello">
select * from mybatis.student
</select>
</mapper>
  • Copyrights © 2015-2023 dwx
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信