目录
步骤
1.配置文件 mybatis.xml
<?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="db.properties">
<!--db.properties优先于内部property -->
<property name="" value=""/>
</properties>
<settings>
<setting name="logImpl" value="LOG4J"/>
<!-- 显示的开启全局缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!--包起别名-->
<typeAliases>
<!-- <typeAlias type="com.lzq.pojo.User" alias="User"/>-->
<package name="com.lzq.pojo"/><!--别名为user-->
<!--还可以在实体类上使用注解@Alias-->
</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>
<!--每一个Mapper.xml对应下面一个<mapper>-->
<mappers>
<mapper resource="com/lzq/dao/UserMapper.xml"/>
</mappers>
</configuration>
2.pojo实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Alias("user")
public class User implements Serializable {
private int id;
private String name;
}
3. SqlSession工具类,生成SqlSession实例
//SqlSessionFactory --> SqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
}
4.Mapper接口
public interface UserMapper {
//@Select("select * from user")
List<User> getUserList();
User getUserByID(int id);
//@Select("select * from user where name like concat('%',#{value},'%')")
List<User> getUserLike(String value);
//分页
List<User> getUserByLimit(Map<String,Object> map);
int addUser(User user);
int updateUser(User user);
int updateUser2(Map<String,Object> map);
int deleteUserByID(int id);
}
5.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">
<mapper namespace="com.lzq.dao.UserMapper">
<!-- 在当前Mapper中使用二级缓存 -->
<cache eviction="FIFO" flushInterval="60000" readOnly="true" size="512"/>
<select id="getUserList" resultType="com.lzq.pojo.User" useCache="true" >
select * from mybatis.user
</select>
<select id="getUserByID" resultType="User" parameterType="int">
select * from mybatis.user where id=#{id}
</select>
<!--结果集映射-->
<resultMap id="UserMap" type="com.lzq.pojo.User">
<!--column数据库字段名 property实体类属性名-->
<result column="name" property="name"/>
</resultMap>
<select id="getUserLike" resultMap="UserMap">
select * from mybatis.user where name like "%"#{value}"%"
</select>
<!--分页查询-->
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
select * from mybatis.user limit #{startIndex},#{pageSize}
</select>
<!-- User对象中的属性可以直接取出来-->
<insert id="addUser" parameterType="com.lzq.pojo.User">
insert into mybatis.user (id,name) values (#{id},#{name})
</insert>
<update id="updateUser" parameterType="com.lzq.pojo.User">
update mybatis.user set name=#{name} where id=#{id}
</update>
<!-- map类型根据key取出-->
<update id="updateUser2" parameterType="map">
update mybatis.user set name=#{Name} where id=#{ID}
</update>
<delete id="deleteUserByID" parameterType="int">
delete from mybatis.user where id=#{id}
</delete>
</mapper>
6.测试
@Test
public void getUser() {
//1.获取SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//2.执行sql 方式一 getMapper
UserMapper userdao = sqlSession.getMapper(UserMapper.class);
List<User> userList = userdao.getUserList();
User user1 = userdao.getUserByID(1);
// //2.执行sql 方式二
// List<User> userList = sqlSession.selectList("com.lzq.dao.UserDao.getUserList");
// User user1 = sqlSession.selectOne("com.lzq.dao.UserDao.getUserByID",1);
for (User user : userList) {
System.out.println(user);
}
System.out.println(user1);
//3.关闭SqlSession
sqlSession.close();
}
其他:log4j属性文件
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/lzq.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{yyyy-MM-dd HH:mm:ss}][%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
多对一处理
多个学生对应一个老师
<!--多对一 联表查询(按照结果嵌套)-->
<select id="getStudent" resultMap="StudentTeacher">
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="StudentTeacher" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<!--复杂的属性teacher单独处理,对象用association 集合用collection-->
<association property="teacher" javaType="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
</association>
</resultMap>
<!--多对一 子查询(按照查询嵌套)-->
<!--select * from student where tid=(select id from teacher where id=tid)-->
<select id="getStudent2" resultMap="StudentTeacher2">
select * from student
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性teacher单独处理,对象用association 集合用collection-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id=#{tid}
</select>
一对多处理
一个老师对应多个学生
<select id="getTeacher" resultType="Teacher">
select * from teacher
</select>
<!--一对多 联表查询-->
<select id="getTeacherStudentByID" resultMap="TeacherStudent">
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 column="tid" property="id"/>
<result column="tname" property="name"/>
<!--复杂的属性students单独处理,对象用association 集合用collection
javeType="" 指定属性类型 集合中的泛型信息用ofType=""-->
<collection property="students" ofType="Student">
<result column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="tid" property="tid"/>
</collection>
</resultMap>
<!--一对多 子查询 select * from teacher where id=#{tid} and id=(select tid from student where tid=id)-->
<select id="getTeacherStudentByID2" resultMap="TeacherStudent2">
select * from teacher where id=#{tid}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<result column="id" property="id"/>
<result column="name" property="name"/>
<!--复杂的属性students单独处理,对象用association 集合用collection
javeType="" 指定属性类型 集合中的泛型信息用ofType=""-->
<collection property="students" column="id" ofType="Student" select="getStudent"/>
</resultMap>
<select id="getStudent" resultType="Student">
select * from student where tid=#{id}
</select>
其他标签的使用
<!--sql片段-->
<sql id="if-title-author">
<if test="title != null">
and title like "%"#{title}"%"
</if>
<if test="author != null">
and author like "%"#{author}"%"
</if>
</sql>
<select id="getBlogIFLike" resultType="Blog" parameterType="map">
select * from blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
<select id="getBlogChooseLike" resultType="Blog" parameterType="map">
select * from blog
<where>
<choose>
<!--选一个!!!!!!!!-->
<when test="title != null">title like "%"#{title}"%"</when>
<when test="author != null">author like "%"#{author}"%"</when>
<otherwise>views = #{views}</otherwise>
</choose>
</where>
</select>
<!-- select * from blog where (id=1 or id=2 or id=3) -->
<select id="getBlogForEach" resultType="Blog" parameterType="map">
select * from blog
<where>
<foreach collection="ids" item="id" open="(" separator="or" close=")">
id=#{id}
</foreach>
</where>
</select>
<update id="updateBlog" parameterType="Blog">
update blog
<set>
<if test="title != null">title=#{title},</if>
<if test="author != null">author=#{author},</if>
<if test="views != null">views=#{views},</if>
</set>
where id=#{id}
</update>
SqlSessionFactoryBuilder
最佳作用域是方法作用域(也就是局部方法变量)。
SqlSessionFactory
最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中。
缓存
一级缓存:默认开启,只在一次sqlSession会话中有效,sqlSession.close就关闭了
一级缓存失效的情况:
- 查询不同的东西
- 增删改操作,可能会改变数据,所以必定刷新缓存
- 查询不同的Mapper.xml(二级缓存也失效)
- 手动清理缓存(sqlSession.clearCache)
二级缓存:namespace级别(Mapper级别),多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
1.映射语句文件中的所有 select 语句的结果将会被缓存。
2.映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
(均可通过标签属性useCache flushCache等设置)
Ps:所有数据先放到一级缓存,只有会话(sqlSession)提交或关闭时才会提交到二级缓存!
依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--在实体类上自动生成get set等方法-->
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<!--<scope>provided</scope>-->
</dependency>
<!-- log4j start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--资源加载,使src/main/java下的资源可以加载进去,默认在src/main/resources-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
八股
Dao 接口的工作原理是 JDK 动态代理,MyBatis 运行时会使用 JDK 动态代理为 Dao 接口生成代理对象,代理对象拦截接口方法,执行 MappedStatement
所代表的 sql,将执行结果返回。
MyBatis与Hibernate:Hibernate属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 MyBatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。