6.1 log4j使用
配套视频:【编程不良人】Mybatis 从入门到精通_哔哩哔哩_bilibili
相关jar包:
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.14.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency>
视频中log4j.properties
## 根日志 ## 日志级别 log4j.rootLogger=ERROR,stdout ## 输出位置 log4j.appender.stdout=org.apache.log4j.ConsoleAppender ## 布局 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout ## 格式 log4j.appender.stdout.layout.conversionPattern=[%p] %d{yyyy-MM-dd} %t %c %m%n ## 子日志 ## 日志级别 log4j.logger.dao=DEBUG ## 监听spring框架的日志级别 log4j.logger.org.springframework=ERROR
StudentDAOTest2.java运行findByIdTest结果
[DEBUG] 2022-04-12 main dao.StudentDAO.findById ==> Preparing: select id,name,age from student where id=? [DEBUG] 2022-04-12 main dao.StudentDAO.findById ==> Parameters: 1(Integer) [DEBUG] 2022-04-12 main dao.StudentDAO.findById <== Total: 1 Student{id=1, name='张三', age=15} Student{id=1, name='张三', age=15}
(待完善)若进行如下细节设置,测试还存在问题:
### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 输出DEBUG级别以上的日志到=D://logs/debug.log ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = D://Software_Development/IDEA_code/logs/debug.log //日志输出路径 可更改 log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 输出ERROR级别以上的日志到=E://logs/error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =D://Software_Development/IDEA_code/logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
测试代码:
package log4j; import org.apache.log4j.Logger; /** * @ClassName TestLog4j * @Description TODO * @Author Jiangnan Cui * @Date 2022/4/9 22:00 * @Version 1.0 */ public class TestLog4j { private static final Logger logger = Logger.getLogger(Logger.class); public static void main(String[] args) { //记录info级别的信息 logger.info("这是info级别的信息"); //记录debug级别的信息 logger.debug("这是debug级别的信息"); //记录error级别的信息 logger.error("这是error级别的信息"); } }
运行结果:
log4j:ERROR setFile(null,true) call failed. java.io.FileNotFoundException: D:\Software_Development\IDEA_code\logs\debug.log \ÈÕÖ¾Êä³ö·¾¶ ¿É¸ü¸Ä (系统找不到指定的路径。) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:270) at java.io.FileOutputStream.<init>(FileOutputStream.java:213) at java.io.FileOutputStream.<init>(FileOutputStream.java:133) at org.apache.log4j.FileAppender.setFile(FileAppender.java:294) at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:165) at org.apache.log4j.DailyRollingFileAppender.activateOptions(DailyRollingFileAppender.java:223) at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:307) at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:172) at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:104) at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:842) at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:768) at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:648) at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:514) at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:580) at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:526) at org.apache.log4j.LogManager.<clinit>(LogManager.java:127) at org.apache.log4j.Logger.getLogger(Logger.java:117) at log4j.TestLog4j.<clinit>(TestLog4j.java:13) log4j:ERROR Either File or DatePattern options are not set for appender [D]. [INFO ] 2022-04-09 23:05:48,318 method:log4j.TestLog4j.main(TestLog4j.java:17) 这是info级别的信息 [DEBUG] 2022-04-09 23:05:48,320 method:log4j.TestLog4j.main(TestLog4j.java:19) 这是debug级别的信息 [ERROR] 2022-04-09 23:05:48,320 method:log4j.TestLog4j.main(TestLog4j.java:21) 这是error级别的信息
参考链接:
6.2 排序(order by)
sql语句:
-- 格式:select 字段1,字段2,... from 表名 order by 字段名 asc/desc -- 其中,asc表示升序(默认的排序方式,可省略不写),desc表示降序 SELECT id,name,age FROM student ORDER BY name
查询结果:
6.3 分页查询(limit)
配套视频:【编程不良人】Mybatis 从入门到精通_哔哩哔哩_bilibili
分页前一般先排序,这里以age进行降序排列,每条显示5条数据为例,进行说明
-- 降序排列 SELECT id,NAME,age FROM student ORDER BY age DESC
-- 语法:limit 起始值 页面的大小 -- 格式:select 字段1,字段2,... from 表名 order by 字段名 limit (n-1)*pageSize,pageSize -- 其中,pageSize表示页面大小,(n-1)*pageSize表示起始值,n表示当前页,总页数=数据总数/页面大小 -- 以每页显示5条数据为例 -- 查询第1页 (1-1)*5=0,5 第1页从0开始,范围为0-4,对应第1到第5条数据 SELECT id,name,age FROM student ORDER BY age DESC LIMIT 0,5
-- 查询第2页 (2-1)*5=5,5 第2页从5开始,范围为5-9,对应第6到第10条数据 SELECT id,NAME,age FROM student ORDER BY age DESC LIMIT 5,5
-- 查询第3页 (3-1)*5=10,5 第3页从10开始,范围为10-14,对应第11到第15条数据 SELECT id,NAME,age FROM student ORDER BY age DESC LIMIT 10,5
StudentDAO.java
/** * @MethodName selectByPage * @Description * @param: pageNow 当前页码 * @param: pageSize 每页显示信息条数 * @return: java.util.List<entity.Student> * @Author Jiangnan Cui * @Date 2022/4/10 16:16 */ List<Student> selectByPage(Map<String,Integer> map);
StudentDAOMapper.xml
<!--分页查询--> <select id="selectByPage" parameterType="map" resultType="entity.Student"> select id,name,age from student order by age desc limit #{pageStart},#{pageSize} </select>
注意:limit后面只能这样传入两个参数,多加操作会报错(就目前认知来看)
测试
/** * @MethodName selectByPage * @Description 分页查询 * @Author Jiangnan Cui * @Date 2022/4/10 16:23 */ @Test public void selectByPage(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class); HashMap<String,Integer> map = new HashMap<>(); map.put("pageStart",0);//第1页从0开始,范围为0-4,对应第1到第5条数据 map.put("pageSize",5); List<Student> students1 = studentDAO.selectByPage(map); System.out.println("---------------第1页----------------"); students1.forEach(student -> System.out.println(student)); map.put("pageStart",5);//第2页从5开始,范围为5-9,对应第6到第10条数据 map.put("pageSize",5); List<Student> students2 = studentDAO.selectByPage(map); System.out.println("---------------第2页----------------"); students2.forEach(student -> System.out.println(student)); map.put("pageStart",10);//第3页从10开始,范围为10-14,对应第11到第15条数据 map.put("pageSize",5); List<Student> students3 = studentDAO.selectByPage(map); System.out.println("---------------第3页----------------"); students3.forEach(student -> System.out.println(student)); sqlSession.close(); }
输出结果:
---------------第1页---------------- Student{id=13, name='慢羊羊', age=70} Student{id=3, name='光头强', age=37} Student{id=5, name='小猪猪', age=28} Student{id=6, name='猪猪侠', age=25} Student{id=9, name='熊大', age=20} ---------------第2页---------------- Student{id=7, name='猪小呆', age=19} Student{id=2, name='小呆呆', age=18} Student{id=10, name='熊二', age=16} Student{id=1, name='张三', age=15} Student{id=12, name='暖羊羊', age=14} ---------------第3页---------------- Student{id=11, name='沸羊羊', age=12} Student{id=4, name='喜洋洋', age=6} Student{id=8, name='皮卡丘', age=5}
参考链接:
6.4 模糊查询(like)
以在name中模糊查询“猪”为例,sql语句:
-- 格式:select 字段1,字段2,... from 表名 where 字段名 like ’%要查询的模糊词%‘ -- %模糊词: 表示前模糊 -- 模糊词%: 表示后模糊 -- %模糊词%:表示中间模糊 SELECT id,name,age FROM student WHERE name LIKE '%猪%'
数据库中查询结果:
StudentDAO.java
//模糊查询 List<Student> selectByLike(String keyWords);
StudentDAOMapper.xml
<!--模糊查询--> <select id="selectByLike" parameterType="String" resultType="entity.Student"> select id,name,age from student where name like "%"#{keyWords}"%"; </select>
注意:
1.模糊查询时要使用“ ”将%括起来而不是’ ‘
2.查询中涉及到中文时,需要在连接数据库时配置characterEncoding=UTF-8
以上两种任一种不设置错误或设置错误均会导致查询不到结果或结果为null!!!
测试
/** * @MethodName selectByLikeTest * @Description 模糊查询 * @Author Jiangnan Cui * @Date 2022/4/10 12:21 */ @Test public void selectByLikeTest(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class); List<Student> students = studentDAO.selectByLike("小"); for (Student student : students) { System.out.println(student); } }
输出结果:
Student{id=5, name='小猪猪', age=28} Student{id=6, name='猪猪侠', age=25} Student{id=7, name='猪小呆', age=19}
6.5 实体类别名设置
实体类起别名对应代码:
<!--给实体类起别名,方便在XxxDAOMapeer.xml文件中进行简写--> <typeAliases> <!--type为要起别名的类对应的全限定名,alias为起的别名--> <typeAlias type="entity.Student" alias="Student"/> </typeAliases>
6.6 引入properties配置文件
jdbc.properties
driver = com.mysql.cj.jdbc.Driver url = jdbc:mysql://localhost:3306/mybatis username = root password = 123456
mybatis-config.xml
<!--配置mybatis环境--> <configuration> <!--引入jdbc.properties配置文件--> <properties resource="jdbc.properties"/> <!-- 配置连接数据库使用的相关参数,default为默认使用的环境 其中,development表示测试环境,可简写为dev produc表示生产环境,可简写为prod --> <environments default="development"> <!--测试环境--> <environment id="development"> <!--事务管理类型:指定事务管理的方式 JDBC--> <transactionManager type="JDBC"/> <!--数据库连接相关配置,动态获取config.properties文件里的内容--> <!--数据源类型:POOLED 表示支持JDBC数据源连接池 UNPOOLED 表示不支持数据源连接池 JNDI 表示支持外部数据源连接池 --> <dataSource type="POOLED"> <!--此处使用的是MySQL数据库,使用Oracle数据库时需要修改,仔细检查各项参数是否正确--> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> </configuration>
6.7 动态sql(sql、include、if、where、choose、when、otherwise、set、trim、foreach)
配套视频:【编程不良人】Mybatis 从入门到精通_哔哩哔哩_bilibili
具体实现:
t_book表
DROP TABLE IF EXISTS `t_book`; CREATE TABLE IF NOT EXISTS `t_book`( `id` VARCHAR(40) PRIMARY KEY, `name` VARCHAR(40), `publishDate` DATE, `price` DOUBLE(7,3), `author` VARCHAR(50) )ENGINE=INNODB CHARSET=utf8; INSERT INTO `t_book` VALUES ('1','六脉神剑',SYSDATE(),120.23,'小黑'), ('2','如来神掌',SYSDATE(),110.23,'小名'), ('3','葵花宝典',SYSDATE(),80.23,'无名'), ('4','星星点灯',SYSDATE(),90.34,'小牛'), ('5','黯然销魂掌',SYSDATE(),67.23,'小伟');
Book.java
package entity; import java.util.Date; /** * @ClassName Book * @Description TODO * @Author Jiangnan Cui * @Date 2022/4/12 15:25 * @Version 1.0 */ public class Book { private String id; private String name; private Date publishDate; private Double price; private String author; @Override public String toString() { return "Book{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", publishDate=" + publishDate + ", price=" + price + ", author='" + author + '\'' + '}'; } public Book(String id, String name, Date publishDate, Double price, String author) { this.id = id; this.name = name; this.publishDate = publishDate; this.price = price; this.author = author; } public Book() { } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getPublishDate() { return publishDate; } public void setPublishDate(Date publishDate) { this.publishDate = publishDate; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } }
a. sql标签
BookDAO.java
/** * @MethodName selectAll * @Description 测试查询所有 * @return: java.util.List<entity.Book> * @Author Jiangnan Cui * @Date 2022/4/12 15:27 */ List<Book> selectAll();
BookDAOMapper.xml
<!--sql语句片段复用标签 id:代表片段的唯一标识 --> <sql id="commonFields"> id,name,publishDate,price,author </sql> <!--查询所有--> <select id="selectAll" resultType="Book"> /* include标签用来指定使用哪个sql片段 refid:表示所使用片段的id */ select <include refid="commonFields"/> from t_book </select>
TestBookDAO.java
/** * @MethodName testSelectAll * @Description 测试查询所有 * @Author Jiangnan Cui * @Date 2022/4/12 16:13 */ @Test public void testSelectAll(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BookDAO bookDAO = sqlSession.getMapper(BookDAO.class); List<Book> books = bookDAO.selectAll(); books.forEach(book -> System.out.println(book)); MybatisUtil.close(); }
b. if标签
BookDAO.java
/** * @MethodName selectByFields * @Description 用来测试动态sql:if、where * @param: book 此处一定要传入对象 * @return: java.util.List<entity.Book> * @Author Jiangnan Cui * @Date 2022/4/12 16:08 */ List<Book> selectByFields(Book book);
BookDAOMapper.xml
<!--根据字段查询:测试动态sql:if、where--> <select id="selectByFields" parameterType="Book" resultType="Book"> select <include refid="commonFields"/> from t_book <where> <if test="name!=null and name!=''"> name=#{name} </if> <if test="author!=null and author!=''"> and author=#{author} </if> </where> </select>
TestBookDAO.java
/** * @MethodName testSelectByFields * @Description 测试 where if * @Author Jiangnan Cui * @Date 2022/4/12 16:13 */ @Test public void testSelectByFields(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BookDAO bookDAO = sqlSession.getMapper(BookDAO.class); List<Book> books = bookDAO.selectByFields(new Book(null, "六脉神剑", null, null, "小黑")); books.forEach(book -> System.out.println("book = " + book)); }
c.choose when otherwise标签
BookDAO.java
/** * @MethodName selectByChoose * @Description 用来测试动态sql:choose、when、otherwise * @param: book * @return: java.util.List<entity.Book> * @Author Jiangnan Cui * @Date 2022/4/12 16:32 */ List<Book> selectByChoose(Book book);
BookDAOMapper.xml
<!--根据选择查询:测试动态sql:choose、when、otherwise--> <select id="selectByChoose" parameterType="Book" resultType="Book"> select <include refid="commonFields"/> from t_book where <choose> <when test="name!=null and name!=''"> name=#{name} </when> <when test="price!=null"> price=#{price} </when> <otherwise> author=#{author} </otherwise> </choose> </select>
TestBookDAO.java
/** * @MethodName testSelectByChoose * @Description 测试 choose、when、otherwise * @Author Jiangnan Cui * @Date 2022/4/12 16:39 */ @Test public void testSelectByChoose(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BookDAO bookDAO = sqlSession.getMapper(BookDAO.class); //List<Book> books = bookDAO.selectByChoose(new Book(null, "六脉神剑",null , null, null)); //List<Book> books = bookDAO.selectByChoose(new Book(null, null,null , null, "小黑")); List<Book> books = bookDAO.selectByChoose(new Book(null, null,null , 110.23, "小黑")); books.forEach(book -> System.out.println("book = " + book)); }
d. set标签
BookDAO.java
/** * @MethodName update * @Description 测试set标签 * @Author Jiangnan Cui * @Date 2022/4/12 16:59 * @param book */ void update(Book book);
BookDAOMapper.xml
<!--测试set标签--> <update id="update" parameterType="Book"> update t_book <set> <if test="name!=null and name!=''"> name=#{name}, </if> <if test="author!=null and author!=''"> author=#{author} </if> </set> where id=#{id} </update>
TestBookDAO.java
/** * @MethodName testUpdate * @Description 测试 set * @Author Jiangnan Cui * @Date 2022/4/12 17:13 */ @Test public void testUpdate(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BookDAO bookDAO = sqlSession.getMapper(BookDAO.class); bookDAO.update(new Book("1","九阴真经",null,null,"小猫")); MybatisUtil.commit(); }
e. trim标签
BookDAO.java
/** * @MethodName update * @Description 测试trim标签 * @Author Jiangnan Cui * @Date 2022/4/12 16:59 * @param book */ void update(Book book);
BookDAOMapper.xml
<!--测试trim标签--> <update id="update" parameterType="Book"> update t_book <!-- prefix:加入前缀 prefixOverrides:去掉前缀 suffix:加入后缀 suffixOverrides:去掉后缀 --> <trim prefix="set" prefixOverrides="," suffix="where"> <if test="name!=null and name!=''"> name=#{name}, </if> <if test="author!=null and author!=''"> author=#{author} </if> </trim> id=#{id} </update>
TestBookDAO.java
/** * @MethodName testUpdate * @Description 测试 trim * @Author Jiangnan Cui * @Date 2022/4/12 17:13 */ @Test public void testUpdate(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BookDAO bookDAO = sqlSession.getMapper(BookDAO.class); bookDAO.update(new Book("1","九阴真经",null,null,"小猫")); MybatisUtil.commit(); }
f. foreach标签
-
批量插入数据
-
-- 批量插入数据使用的sql语句:insert into 表名 (字段一,字段二,字段三) values(aaa,bbb,ccc),(ddd,eee,fff),(ggg,hhh,lll)
-
BookDAO.java
/** * @MethodName insertAll * @Description 测试foreach遍历 * @param: books * @Author Jiangnan Cui * @Date 2022/4/12 17:44 */ public void insertAll(List<Book> books);
BookDAOMapper.xml
<!-- 批量插入数据 SELECT LAST_INSERT_ID():获得刚insert进去记录的主键值,只适用于自增主键 keyProperty:将查询到主键值设置到parameterType指定的对象的那个属性 order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来讲它的执行顺序 resultType:指定SELECTLAST_INSERT_ID()的结果类型 参考链接: http://www.javashuo.com/article/p-fcnlzrmg-nw.html collection:用来书写遍历集合类型 index : 当前遍历的索引,从0开始 item : 当前遍历元素的别名 open : 在第一次遍历之前加入的语句 close : 在最后一次遍历之后加入的语句 separator: 在每一次遍历之后加入的语句,最后一次不加入 --> <insert id="insertBatch" parameterType="java.util.List" useGeneratedKeys="true"> <selectKey resultType="long" keyProperty="id" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> insert into t_book (<include refid="commonFields"/>) values <foreach collection="list" item="book" index="index" separator=","> ( #{book.id},#{book.name},#{book.publishDate},#{book.price},#{book.author} ) </foreach> </insert>
TestBookDAO.java
/** * @MethodName testInsertBatch * @Description 测试foreach遍历 批量插入数据 * @Author Jiangnan Cui * @Date 2022/4/12 17:52 */ @Test public void testInsertBatch(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BookDAO bookDAO = sqlSession.getMapper(BookDAO.class); bookDAO.insertBatch(Arrays.asList( new Book(UUID.randomUUID().toString(), "海边的卡夫卡", new Date(), 23.45, "村上春树"), new Book(UUID.randomUUID().toString(),"阿弥陀佛么么哒",new Date(),25.36,"大冰"), new Book(UUID.randomUUID().toString(),"兄弟",new Date(),34.56,"余华") )); MybatisUtil.commit(); }
-
批量更新数据
-
-- 批量更新数据使用的sql语句:
UPDATE 表名
SET aa = CASE id
WHEN 1 THEN 'aaa'
WHEN 2 THEN 'bbb'
WHEN 3 THEN 'ccc'
END
,SET bb = CASE id
WHEN 1 THEN 'ddd'
WHEN 2 THEN 'eee'
WHEN 3 THEN 'fff'
END
WHERE id IN (1,2,3)
-
BookDAO.java
/** * @MethodName updateBatch * @Description 测试foreach遍历 批量更新数据 * @param: books * @Author Jiangnan Cui * @Date 2022/4/12 17:44 */ public void updateBatch(List<Book> books);
BookDAOMapper.xml
<!-- 批量更新数据 --> <update id="updateBatch"> update t_book set name = <foreach collection="list" item="book" index="index" separator=" " open="case id" close="end"> when #{book.id} then #{book.name} </foreach> ,price = <foreach collection="list" item="book" index="index" separator=" " open="case id" close="end"> when #{book.id} then #{book.price} </foreach> ,author = <foreach collection="list" item="book" index="index" separator=" " open="case id" close="end"> when #{book.id} then #{book.author} </foreach> where id in <foreach collection="list" item="book" index="index" separator="," open="(" close=")"> #{book.id} </foreach> </update>
TestBookDAO.java
/** * @MethodName testUpdateBatch * @Description 测试foreach遍历 批量更新数据 * @Author Jiangnan Cui * @Date 2022/4/12 17:52 */ @Test public void testUpdateBatch(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BookDAO bookDAO = sqlSession.getMapper(BookDAO.class); bookDAO.updateBatch(Arrays.asList( new Book("1", "喜羊羊", new Date(),11.11, "猪猪侠"), new Book("2","暖羊羊",new Date(),22.22,"小呆呆"), new Book("3","沸羊羊",new Date(),33.33,"波比") )); MybatisUtil.commit(); }