log4 java:Java日志的实现
日志---->控制台
boolean flag = true;
public void isPrint(String msg){
if (flag){
System.out.print(msg);
}else{
}
}
在核心配置文件中,加入Log4j依赖
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
**log4j的配置文件**
log4j.properties
### Log4j配置 ###
#定义log4j的输出级别和输出目的地(目的地可以自定义名称,和后面的对应)
#[ level ] , appenderName1 , appenderName2
log4j.rootLogger=DEBUG,console,file
#-----------------------------------#
#1 定义日志输出目的地为控制台
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
####可以灵活地指定日志输出格式,下面一行是指定具体的格式 ###
#%c: 输出日志信息所属的类目,通常就是所在类的全名
#%m: 输出代码中指定的消息,产生的日志具体信息
#%n: 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#-----------------------------------#
#2 文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.file = org.apache.log4j.RollingFileAppender
#日志文件输出目录
log4j.appender.file.File=log/info.log
#定义文件最大大小
log4j.appender.file.MaxFileSize=10mb
###输出日志信息###
#最低级别
log4j.appender.file.Threshold=ERROR
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#-----------------------------------#
#3 druid
log4j.logger.druid.sql=INFO
log4j.logger.druid.sql.DataSource=info
log4j.logger.druid.sql.Connection=info
log4j.logger.druid.sql.Statement=info
log4j.logger.druid.sql.ResultSet=info
#4 mybatis 显示SQL语句部分
log4j.logger.org.mybatis=DEBUG
#log4j.logger.cn.tibet.cas.dao=DEBUG
#log4j.logger.org.mybatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.org.mybatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.org.mybatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
#log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
Mybatis的日志实现
1.默认的日志实现
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
2.log4j日志的实现
导包
配置文件编写
mybatis核心文件中进行配置
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
6.分页的实现
mysql的分页语句
select * from user limit #{startIndex},#{pageSize}
# startIndex:起始位置,默认是0开始
# pageSize:页面大小
#如何计算出当前页面
currentPage=(currentPage-1)*pageSize
使用limit实现分页
1.编写dao接口
//查询全部用户实现分页
List<User> selectUserByLimit(Map<String,Integer> map);
2编写对应mapper映射文件的方法
【参数我们可以使用map封装,方便参数传递】
<select id="selectUserByLimit" parameterType="Map" resultType="User">
select * from mybatis.user limit #{startIndex},#{pageSize}
</select>
3.测试
【模拟分页数据:currentPage,pageSize】
@Test
public void selectUserByLimit(){
//创建sqlSession
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
//准备数据
int currentPage = 2;//当前是第几页
int pageSize = 2; //页面大小
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("startIndex",(currentPage-1)*pageSize);
map.put("pageSize",pageSize);
//测试
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> users = mapper.selectUserByLimit(map);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();//关闭连接
}
使用RowBounds实现分页
1.写接口
//查询全部用户实现分页使用RowBounds
List<User> selectUserByRowBounds();
2.写Mapper映射文件
<select id="selectUserByRowBounds" resultType="User">
select * from mybatis.user
</select>
3.编写测试代码
@Test
public void selectUserByRowBounds(){
//创建sqlSession
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
int currentPage = 2; //当前页
int pageSize = 2; //页面大小
RowBounds rowBounds = new RowBounds((currentPage - 1) * pageSize, pageSize);
//注意点;使用RowBounds就不能使用getMapper了
//selectList: 接收一个List
//selectMap: 接收一个Map
//selectOne : 接收只有一个对象的时候
List<User> users = sqlSession.selectList("com.kuang.dao.UserDao.selectUserByRowBounds", null, rowBounds);
for (User user : users) {
System.out.println(user);
}
}
limit和rowBounds区别
- rowBounds 本质就是封装了limit
- limit 是在SQL层面实现分页
- rowBounds 在代码层面实现分页
面向接口编程
提出的原因:解耦,方便拓展,提高代码的复用性,上层不用管下层实现,只用去调用对应的接口即可。规范性好。
面向过程编程:随着系统越来越大,我们无法使用面向过程的思想满足。面对对象。
面向对象编程:所有系统耦合性高,所有的功能都是由许许多多不同的对象去完成的
接口&抽象类
面向接口编程:约束开发人员操作,而且方便扩展以及规划。
更深层次的分离:定义与实现的一个分离;
接口可以反映一个开发人员的水平高低以及对系统架构理解;
7.使用注解开发
早期的,mybatis都是使用xml进行配置的,直到注解的出现,注解可以替代一些xml中的配置。
连xml配置都不要了!
CRUD的注解:
- @insert()
- @delete()
- @update()
- @select()
思考?我们之前的代码,还能在优化吗?
日志,工具类,配置文件,别名… 事务
mybaits开发人员也想到了,有一个构造器,可以实现事务自动提交。
优化项目
事务优化:自动提交事务
//获得一个带事务自动提交功能的SqlSession公共的方法
public static SqlSession getSqlSession(){
//自动提交事务
return sqlSessionFactory.openSession(true);
}
别名优化:pojo包下类自动设置别名
<!--配置别名-->
<typeAliases>
<!--<typeAlias type="com.kuang.pojo.User" alias="User"/>-->
<package name="com.kuang.pojo"/>
</typeAliases>
mapper映射文件路径修改
<mappers>
<!--class对应的是一个接口类-->
<!--resource对应的是一个接口类的映射文件-->
<mapper class="com.kuang.dao.UserDao"/>
</mappers>
使用注解进行开发
UserDao.java
package com.kuang.dao;
import com.kuang.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserDao {
//查询全部用户
@Select("select * from user")
List<User> getUserList();
//通过ID查询用户
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);
//添加用户
@Insert("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
int addUser(User user);
//修改用户信息
@Update("update user set name = #{name}, pwd = #{pwd} where id = #{id}")
int updateUser(User user);
//删除用户
@Delete("delete from user where id =#{uid}")
int deleteUser(@Param("uid") int id);
}
mybatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置文件修改-->
<properties resource="database.properties"/>
<!--Mybatis设置-->
<settings>
<!--默认日志实现-->
<!--<setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--Log4j实现-->
<setting name="logImpl" value="LOG4J"/>
</settings>
<!--配置别名-->
<typeAliases>
<!--<typeAlias type="com.kuang.pojo.User" alias="User"/>-->
<package name="com.kuang.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--class对应的是一个接口类-->
<!--resource对应的是一个接口类的映射文件-->
<mapper class="com.kuang.dao.UserDao"/>
</mappers>
</configuration>
测试类
package com.kuang.dao;
import com.kuang.pojo.User;
import com.kuang.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import sun.rmi.server.UnicastServerRef;
import java.util.List;
public class UserDaoTest {
@Test
public void getUserList(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();//关闭sqlSession;
}
@Test
public void getUserById(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.getUserById(1);
System.out.println(user);
sqlSession.close();//关闭sqlSession;
}
@Test
public void addUser(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = new User(5, "阿猫", "like-dog");
int i = mapper.addUser(user);
System.out.println(i);
sqlSession.close();//关闭sqlSession;
}
@Test
public void updateUser(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = new User(5, "阿狗", "like-cat");
int i = mapper.updateUser(user);
System.out.println(i);
sqlSession.close();//关闭sqlSession;
}
@Test
public void deleteUser(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.deleteUser(5);
System.out.println(i);
sqlSession.close();//关闭sqlSession;
}
}
注意事项
- 开启事务自动提交了
- @param参数尽量都写上,如果有多个参数,就必须填写。
多对一处理
多个对象对应一个对象
比如:你们都是我的学生 ,多个学生对应一个老师
掌握两个单词:
-
association — 联系 ,关联 多个人可以关联一个人。
-
collection — 集合 一个人有一个集合,包含多个人。
-
发现是多对一业务情况,我们需要使用association 标签进行关联
多对一的处理方式使用数据库的思想处理:联表查询
- 定义dao接口
List<Student> getStudents();
2.编写查询语句
- 查询学生信息 id name tid , 由于我们要得到老师的信息,我们需要联表查询
- 查询老师的信息 id name 。
<!--遇到问题:学生类中关联老师: 多个学生对应一个老师 -->
<!--<select id="getStudents" resultType="Student">-->
<!--select s.id,s.name,t.name from mybatis.student as s,mybatis.teacher as t-->
<!--where s.tid = t.id-->
<!--</select>-->
<!--解决问题方式一:按查询结果嵌套处理,模拟数据库思想;
-->
<select id="getStudents" resultMap="StudentTeacher">
select * from mybatis.student
</select>
<resultMap id="StudentTeacher" type="Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--属性和字段对应 , 类和表对应 , 对象和记录
关联一个字段
需求:拿到老师这个类的属性
association : 关联,多对一
column : 数据库对应的列名
property : 对应属性名
javaType : 多对一字段对应的Java类型
select : 关联一个语句
-->
<association column="tid" property="teacher" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from mybatis.teacher where id = #{id}
</select>
测试类
@Test
public void getStudents(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List<Student> students = mapper.getStudents();
for (Student student : students) {
System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
}
}
多对一的处理方式二
1.编写接口
List<Student> getStudentsTwo();
2.编写处理的mapper
- 查询学生id,学生姓名,老师姓名,需要从学生表和老师表中查询
- 学生对应的类进行映射,发现老师一个对象 , 所以关联一个对象;
<!-- 解决方式二:一个resultMap解决 , 模拟面向对象的思想-->
<select id="getStudentsTwo" resultMap="StudentTeacher2">
select s.id,s.name,t.name as tname from mybatis.student as s, mybatis.teacher as t
where s.tid = t.id
</select>
<!--设置结果集映射ResultMap -->
<resultMap id="StudentTeacher2" type="Student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--直接关联一个老师-->
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
3.测试类
@Test
public void getStudentsTwo(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List<Student> students = mapper.getStudentsTwo();
for (Student student : students) {
System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
}
}
**总结**
1. mybatis中遇到多对一的情况,要使用关联映射处理:使用association
- 两种处理思路:
- 数据库思想 : 联表查询
- OOP思想 :关联对象
一对多处理
一个老师对应多个学生
一对多的业务:使用collection处理
环境搭建
一个老师对应对个学生
public class Teacher {
private int id;
private String name;
//一个老师对应对个学生
private List<Student> students;
}
编写代码
编写dao接口
package com.kuang.dao;
import com.kuang.pojo.Teacher;
public interface TeacherDao {
//获得一个老师下的所有学生信息; 老师是包含学生的集合;
Teacher getTeacher(int id);
Teacher getTeacherTwo(int id);
}
对应的mapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.dao.TeacherDao">
<!--一对多的处理-->
<!--面向对象方式解决-->
<select id="getTeacher" resultMap="TeacherStudent">
select s.name sname,s.id sid,t.id tid, t.name tname
from mybatis.student as s,mybatis.teacher as t
where s.tid = t.id and t.id = #{id}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</collection>
</resultMap>
<!--数据库思想-->
<select id="getTeacherTwo" resultMap="TeacherStudent2">
select * from mybatis.teacher where id = #{id}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" column="id" select="T2"/>
</resultMap>
<select id="T2" resultType="Student">
select * from mybatis.student where tid = #{id}
</select>
</mapper>
测试类:
package com.kuang.dao;
import com.kuang.pojo.Teacher;
import com.kuang.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class TeacherDaoTest {
@Test
public void getTeacher(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
Teacher teacher = mapper.getTeacher(1);
System.out.println(teacher.getName());
System.out.println(teacher.getStudents());
}
@Test
public void getTeacherTwo(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
Teacher teacher = mapper.getTeacherTwo(1);
System.out.println(teacher.getName());
System.out.println(teacher.getStudents());
}
}
总结
多对一:association 关联
一对多:collection 集合
两种解决方式:
- 面对对象的思想:关联对象
- SQL语句思想:联表查询
动态SQL&缓存
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。
动态SQL就是指根据不同查询条件,生成不同的SQL语句
在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
if
参数test:里面的表达式如果为ture则执行,否则不执行
if(title != null)
<if test="title != null">
AND title like #{title}
</if>
choose
有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
switch (exp){
case 1:
break;
case 2:
break;
}
</select>
trim[where,set]
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
<trim prefix="SET" suffixOverrides=",">
...
</trim>
foreach
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
代码测试
测试模糊查询
接口编写
//模糊查询,可以通过自定义条件查询
List<User> getUserByLike(Map<String,Object> map);
映射文件编写
<select id="getUser" resultType="User">
select * from mybatis.user
</select>
<select id="getUserByLike" resultType="User" parameterType="Map">
select * from mybatis.user
<where>
<if test="name!=null">
name like CONCAT('%',#{name},'%')
</if>
<if test="id!=null">
and id = #{id}
</if>
</where>
</select>
测试类
@Test
public void getUserByLike(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Map<String,Object> map = new HashMap<String,Object>();
map.put("name","秦");
map.put("id",1);
List<User> users = mapper.getUserByLike(map);
for (User user : users) {
System.out.println(user);
}
}
注意点:太过复杂的逻辑不建议使用动态SQL,简单的话可以直接使用动态SQL实现;
缓存
如果开启缓存,
在mapper映射文件中,添加一个标签
<!--开启缓存-->
<cache/>
如果要CRUD操作要查询结果需要缓存,可以使用usrCache;
<!--
useCache: 是否开启缓存
使用缓存可以解决问题:
查询出来的结果暂时保存着,消耗内存资源;
如果短时间查询同样的语句比较多,可以提高速度;
-->
<select id="getUser" resultType="User" useCache="true">
select * from mybatis.user
</select>