关于MyBatis2的重要笔记在下面的百度网盘连接中,欢迎大家一起学习
链接:https://pan.baidu.com/s/1zGAtbdQElMTgzUZUSg033w
提取码:2ywn
下面就我学习过程中的一些容易忘记的点再做一次记录,以便后续复习
第一步:编写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>
<!--导入db.properties配置文件————类路劲,表明这个文件就在resource下面-->
<properties resource="db.properties"></properties>
<settings>
<!--<setting name="logImpl" value="STDOUT_LOGGING"/> 标准日志工厂,直接用就行-->
<setting name="logImpl" value="LOG4J"/> <!-- 需要配置,具体配置内容在下方 -->
</settings>
<!--起别名,这样resultType,paramType等不需要再去写对象对应的类路径,直接写类首字母小写即可-->
<typeAliases>
<!--给某一个具体的实体类起别名-->
<typeAlias type="com.it.bean.User" alias="User1"></typeAlias>
<!--把这个包里面的所有类都起了别名,别名为类名的首字母小写,大写也可以-->
<package name="com.it.bean"/>
</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>
<!--<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis2?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
</environment>-->
</environments>
<!--每一个数据库接口对应的Mapper.xml都需要在这个配置文件中注册-->
<mappers>
<!--根据类路径,当和接口在一块时要写成com/it/dao/UserMapper.xml,就在resource下面就直接写-->
<mapper resource="com/it/dao/UserMapper.xml"/>
<!--根据包,这个包下面的所有接口都映射到,要求是配置文件要和接口名相同
且位于同一目录下,因此要么和接口放一块,要么在resource下面创相同的文件夹再放置进去-->
<package name="com.it.dao"></package>
<!--总结:接口很多用包,接口不多一个一个写,毕竟这个不用同名,不用在同一路径-->
</mappers>
</configuration>
第二步:编写MyBatis工具类
// 从 SqlSessionFactory 中获取 SqlSession
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory;
// 这是死的,必须要有
static {
// 使用Mybatis第一步:获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
// 获取SqlSession
public static SqlSession getSqlSession(){
// 设置为true表示自动提交,不需要手动提交了
SqlSession sqlSession = sqlSessionFactory.openSession(true); // 用完了要记得关闭
return sqlSession;
}
}
第三步:编写数据库接口
这个按照具体的情况而自行编写
第四步:编写数据库接口对应的mapper.xml
这里要注意,数据库的接口肯定是放在java下面的包里面,而mapper习惯放到resource下面,这时要求mapper在resource下面的路径与接口在java中的路径一致
一个mapper接口对应一个mapper.xml
<?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">
<!--namespace命名空间,绑定一个Mapper接口,为这个mapper接口的类路径-->
<mapper namespace="com.it.dao.UserMapper">
<resultMap id="UserMap" type="user">
<!--column数据库中的字段,property是javabean中的属性,一一映射,而且只需要把不一样的映射就好了-->
<result column="pwd" property="password"></result>
</resultMap>
<!--select查询,id对应接口中的方法名字-->
<select id="getUserList" resultMap="UserMap">
select * from user;
</select>
<!--id————mapper接口中的某个方法名
parameterType————参数类型
* 当传递的参数只有一个可直接写
* 当传递的参数有多个,可将其封装在map内部,取值时为#{key}
* 当传递的参数为javabean对象时,取值直接为#{bean对象属性}
* 当传递的参数为@param类型,则为#{id},一般多于一个没有用map时必须写@param
resultType————返回值类型
* 基本数据类型,则为_数据类型,如_int
* 对象数据类型,则为首字母小写,如integer,string
* 自己封装的javabean对象类型,由于起了别名,可直接写首字母小写的类名,这里要注意,这表明查询出来的数据库属性名要和javabean中的属性名要对应,名字要相同,不同的只会注入null,因此如果不同,就要使用到resultMap
* List类型:resultType写List中元素的类型
* Map类型:单条记录:resultType =map 多条记录:resultType=Map中value的类型-->
sql语句中用#{}来取参数值
-->
<select id="getUserLike" parameterType="String" resultType="com.it.bean.User">
select * from user where name like #{value};
</select>
<insert id="addUser2" parameterType="Map">
insert into user(id, name, pwd) values (#{id}, #{name}, #{pwd});
</insert>
<update id="updateUser" parameterType="com.it.bean.User">
update user set name = #{name}, pwd = #{pwd} where id=#{id};
</update>
<delete id="deleteUserById" parameterType="Integer">
delete from user where id=#{id};
</delete>
</mapper>
第四步:测试
@Test
public void testGetUserLike(){
// 首先获得sqlSession对象
SqlSession sqlSession = MyBatisUtil.getSqlSession();
// 通过sqlSession获得对应接口对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserLike("%李%");
for (User user : userList) {
System.out.println(user);
}
// 所有的增删改是需要提交事务的
// sqlSession.commit();
// 关闭sqlSession
sqlSession.close();
}
补充
1、可能出现问题说明——Maven静态资源过滤问题
在pom.xml中加入这段代码就可以解决
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include> </includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
2、 @Param属性
接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!
• 有时候根据业务的需求,可以考虑使用map传递参数!
1、在接口方法的参数前加 @Param属性
2、Sql语句编写的时候,直接取@Param中设置的值即可,不需要单独设置参数类型
//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);
<select id="selectUserByNP" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>
3、配置log4j
首先编写log4j配置文件,在resource下面
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/java.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
在程序中使用Log4j进行输出!
//注意导包:org.apache.log4j.Logger static Logger logger = Logger.getLogger(MyTest.class);
@Test
public void selectUser() {
logger.info("info:进入selectUser方法");
logger.debug("debug:进入selectUser方法");
logger.error("error: 进入selectUser方法");
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectUser();
for (User user: users){
System.out.println(user);
}
session.close();
}
4、使用注解开发,由于注解开发的功能并不强大,往往mybatis是使用xml来进行开发的
5、分页方式——一般直接使用mysql种的limit标签,或者使用pageHelper插件,自行学习
6、多对一关系的处理,如多个学生对应一个老师,学生的javabean中有老师对象的属性
老师的javabean正常些数据库中的那几个属性,学生的不需要老师的id,直接给一个老师的对象
// 学生关联一个老师
private Teacher teacher;
查询时有两种方式:按查询嵌套处理和按结果嵌套处理,这里我只讲按结果嵌套处理
<select id="getStudents2" resultMap="StudentTeacher2" >
select s.id sid,
s.name sname,
t.id tid,
t.name tname
from student s,teacher t where s.tid = t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<!--对于属性是对象的复杂类型,我们需要单独处理,这里对象用association,集合用collection
property:注入给实体类的哪个属性
javaType:把sql语句的查询结果封装给某个类的对象-->
<association property="teacher" javaType="teacher">
<result property="id" column="tid" />
<result property="name" column="tname"/>
</association>
</resultMap>
7、一对多关系
如一个老师对应多个学生,此时学生的javabean正常写数据库中的属性,而老师的要多一个若干学生对象的集合
// 一个老师拥有多个学生
private List<Student> students;
<select id="getTeacher" resultMap="TeacherStudent" parameterType="integer">
select t.id tid, t.name tname, s.id sid, s.name sname
from teacher t, student s where t.id = s.tid and t.id = #{tid};
</select>
<resultMap id="TeacherStudent" type="teacher">
<result property="id" column="tid" />
<result property="name" column="tname" />
<!-- • JavaType是用来指定javabean中属性的类型
• ofType指定的是映射到list集合属性中javabean的类型 -->
<collection property="students" ofType="student">
<result property="id" column="sid" />
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
动态SQL——重点
写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。
那么怎么去解决这个问题呢?这就要使用 mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。
插一句:使用UUID生成随机的id
public static String getId(){
return String.valueOf(UUID.randomUUID()).replaceAll("-", "");
}
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
<!--choose标签类似于switch,只会选择一个满足的执行,从上到下选择一个-->
<select id="queryBlogChoose" resultType="blog" parameterType="map">
select * from blog
<where>
<choose>
<when test="title != null">
and title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
<update id="updateBlogBySet" parameterType="map">
update blog
<set>
/*sql片段复用*/
<include refid="if_title_author"></include>
</set>
where id = #{id};
</update>
<!--定义sql片段,提高代码的可重用性,里面不要有where-->
<sql id="if_title_author">
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author},
</if>
</sql>
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id = #{id}
</foreach>
</where>
</select>
缓存
1、什么是缓存 [ Cache ]?
• 存在内存中的临时数据。
• 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
2、为什么使用缓存?
• 减少和数据库的交互次数,减少系统开销,提高系统效率。
3、什么样的数据能使用缓存?
• 经常查询并且不经常改变的数据。
MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存),与数据库同一次会话期间查询到的数据会放在本地缓存中。
二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
一级缓存失效的四种情况
一级缓存是SqlSession级别的缓存,是一直开启的,我们关闭不了它;
一级缓存失效情况:没有使用到当前的一级缓存,效果就是,还需要再向数据库中发起一次查询请求!
1、执行了增删改操作,可能会改变原来的数据,所以系统必定会刷新缓存
2、sqlSession不同,我们的一级缓存是以sqlSession级别缓存,换了sqlSession肯定不一样了
3、sqlSession相同,但执行不同的数据,此时缓存里面没有这个数据,肯定失效
4、sqlSession相同,但手动执行清除一级缓存: sqlSession.clearCache();
二级缓存
• 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
• 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
• 工作机制
一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
新的会话查询信息,就可以从二级缓存中获取内容;
不同的mapper查出的数据会放在自己对应的缓存(map)中;
使用步骤
1、开启全局缓存 【mybatis-config.xml】
<setting name="cacheEnabled" value="true"/>
2、去每个mapper.xml中配置使用二级缓存,这个配置非常简单;【xxxMapper.xml】
<cache/>
查出的数据都会被默认先放在一级缓存中
只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中
缓存顺序:
1、先看二级缓存中有没有
2、再看一级缓存中有没有
3、查询数据库