1. Mybatis编程式使用(单独使用)
1.1 mybatis和Mysql jar 包依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<!-- mysql driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
<scope>runtime</scope>
</dependency>
1.2 全局配置文件mybatis-config.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>
<!-- 参数设置 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
<!--<setting name="proxyFactory" value="CGLIB" />-->
<setting name="cacheEnabled" value="false" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="jdbcTypeForNull" value="NULL"/>
<setting name="callSettersOnNulls" value="true"/>
</settings>
<!-- mybatis分页插件-->
<plugins>
<plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
<property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect"/>
</plugin>
</plugins>
</configuration>
1.3 映射器 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.inspur.icity.business.neighborhoodbar.logic.repo.SayingRepo">
<!-- 返回说说以及评论回复的数据格式所需的映射文件-->
<resultMap id="SayingMap" type="Saying">
<id column="saying_id" property="saying_id" jdbcType="INTEGER"/>
<result column="custId" property="custId" jdbcType="VARCHAR"/>
<result column="userType" property="userType" jdbcType="VARCHAR"/>
<result column="sayAuthor" property="sayAuthor" jdbcType="VARCHAR"/>
<result column="phone" property="phone" jdbcType="VARCHAR"/>
<result column="theme" property="theme" jdbcType="VARCHAR"/>
<result column="sayingContent" property="sayingContent"/>
<result column="sayingPicture" property="sayingPicture"/>
<result column="likes" property="likes" jdbcType="INTEGER"/>
<result column="commentNum" property="commentNum" jdbcType="INTEGER"/>
<result column="pass" property="pass" jdbcType="VARCHAR"/>
<result column="submitTime" property="submitTime" jdbcType="TIMESTAMP"/>
<result column="passTime" property="passTime" jdbcType="TIMESTAMP"/>
<collection property="comments" ofType="Comment" column="sayingId">
<id column="comment_id" property="comment_id" jdbcType="INTEGER"/>
<result column="sayingId" property="sayingId" jdbcType="INTEGER"/>
<result column="commentor" property="commentor" jdbcType="VARCHAR"/>
<result column="commentorId" property="commentorId" jdbcType="VARCHAR"/>
<result column="commentContent" property="commentContent"/>
<result column="commentLikes" property="commentLikes" jdbcType="INTEGER"/>
<result column="commentTime" property="commentTime" jdbcType="TIMESTAMP"/>
<collection property="replyComments" ofType="ReplyComment" column="commentId">
<id column="reply_id" property="reply_id" jdbcType="INTEGER"/>
<result column="sayingId" property="sayingId" jdbcType="INTEGER"/>
<result column="commentId" property="commentId" jdbcType="INTEGER"/>
<result column="replier" property="replier" jdbcType="VARCHAR"/>
<result column="replierId" property="replierId" jdbcType="VARCHAR"/>
<result column="toCommentor" property="toCommentor" jdbcType="VARCHAR"/>
<result column="toCommentId" property="toCommentId" jdbcType="VARCHAR"/>
<result column="replyContent" property="replyContent"/>
<result column="replyLikes" property="replyLikes"/>
<result column="replyTime" property="replyTime" jdbcType="TIMESTAMP"/>
</collection>
</collection>
</resultMap>
<select id="selectSayingById" resultMap="SayingMap" parameterType="long">
SELECT
*
FROM
(
SELECT
*
FROM
neighborhood_saying s
LEFT JOIN neighborhood_firstcomment fc ON s.saying_id = fc.sayingId
WHERE
s.saying_id = #{sayingId}
ORDER BY
fc.commentTime DESC
) tmp
LEFT JOIN neighborhood_replycomment rc ON tmp.comment_id = rc.commentId
ORDER BY
rc.replyTime DESC;
</select>
<!-- 将用户点赞状态一同返回给前端-->
<select id="getLikeStatusAndSayingBySayingId" resultType="java.util.Map">
SELECT
IF( l.id > 0, 1, 0 ) AS likeStatus,
s.saying_id,
s.custId,
s.userType,
s.sayAuthor,
s.phone,
s.theme,
s.sayingContent,
s.sayingPicture,
s.likes,
s.commentNum,
s.pass,
s.submitTime,
s.passTime
FROM
neighborhood_saying s
LEFT JOIN neighborhood_like l ON s.saying_id = l.sayingId
AND l.custId = #{custId}
AND likeType = '0'
WHERE
s.saying_id = #{sayingId}
</select>
<!-- 获取所有审核过的贴子 区分模块-->
<select id="findAllSayings" resultType="Saying">
select * from neighborhood_saying
where pass='1'
<if test="theme != null and theme != ''">
and
theme = #{theme}
</if>
;
</select>
<!-- 获取自己的贴子-->
<select id="findMySaying" resultType="Saying">
select * from neighborhood_saying where custId=#{custId};
</select>
<!-- 判断是否自己的贴子-->
<select id="isMySaying" resultType="java.util.Map">
select * from neighborhood_saying where custId=#{custId} and saying_id = #{sayingId};
</select>
<!-- 提供管理平台关键词 手机号 姓名 时间 模块 审核状态 身份查询-->
<select id="getSayingByWhat" resultType="Saying">
SELECT
saying_id,
custId,
userType,
sayAuthor,
phone,
theme,
sayingContent,
sayingPicture,
likes,
commentNum,
pass,
submitTime,
passTime
FROM
neighborhood_saying
WHERE
1=1
<if test="userType != null and userType != ''">
and
userType = #{userType}
</if>
<if test="sayAuthor != null and sayAuthor != ''">
and
sayAuthor = #{sayAuthor}
</if>
<if test="phone != null and phone != ''">
and
phone = #{phone}
</if>
<if test="theme != null and theme != ''">
and
theme = #{theme}
</if>
<if test="keyWord != null and keyWord != ''">
and
sayingContent like concat('%',#{keyWord},'%')
</if>
<if test="pass != null and pass != ''">
and
pass = #{pass}
</if>
<if test="startTime != null and startTime != ''">
and
submitTime > #{startTime}
</if>
<if test="endTime != null and endTime != ''">
and
submitTime < #{endTime}
</if>
order by submitTime desc;
</select>
<!-- 管理平台审核状态-->
<update id="passSaying">
update neighborhood_saying set pass = '1', passTime=now() where saying_id = #{sayingId};
</update>
<!-- 及时更新点赞数量和评论数-->
<update id="increaseLikes">
update neighborhood_saying set likes = likes+1 where saying_id = #{sayingId};
</update>
<update id="reduceLikes">
update neighborhood_saying set likes = likes-1 where saying_id = #{sayingId};
</update>
<!-- 增加说说评论数量-->
<update id="increaseCommentNum">
update neighborhood_saying set commentNum = commentNum+1 where saying_id = #{sayingId};
</update>
<!-- 减少说说评论数量-->
<update id="reduceCommentNum">
update neighborhood_saying set commentNum = commentNum-1 where saying_id = #{sayingId};
</update>
<!-- 发表说说-->
<insert id="add" useGeneratedKeys="true" keyProperty="id" parameterType="Saying">
INSERT INTO neighborhood_saying
( saying_id, custId, userType, sayAuthor, phone, theme, sayingContent, sayingPicture, likes, commentNum, pass, submitTime, passTime )
VALUES
(#{saying_id}, #{custId}, #{userType}, #{sayAuthor}, #{phone}, #{theme}, #{sayingContent}, #{sayingPicture}, #{likes}, #{commentNum}, #{pass}, now(), #{passTime});
</insert>
<!-- 删除说说 同时删除对应的以及评论和回复 以及点赞记录-->
<delete id="remove">
delete from neighborhood_saying where saying_id = #{sayingId};
delete from neighborhood_firstcomment where sayingId = #{sayingId};
delete from neighborhood_replycomment where sayingId = #{sayingId};
delete from neighborhood_like where sayingId = #{sayingId};
</delete>
</mapper>
1.4 Mapper接口
/**
* @Description: mapper
* @Author create by xuchao
* @Date 2020/7/7 21:14
*/
@Mapper
public interface SayingRepo {
List<Saying> getDemoByProperty(String property);
List<Saying> getSayingByWhat(@Param("sayAuthor") String sayAuthor, @Param("phone") String phone,
@Param("keyWord") String keyWord, @Param("theme") String theme,
@Param("startTime") String startTime, @Param("endTime") String endTime,
@Param("userType") String userType, @Param("pass") String pass,
PageBounds pageBounds);
List<Saying> findMySaying(@Param("custId") String custId);
List<Saying> findAllSayings(@Param("theme") String theme);
Saying selectSayingById(@Param("sayingId") Long sayingId);
Map<String, Object> isMySaying(@Param("sayingId") Long sayingId, @Param("custId") String custId);
Map<String, Object> getLikeStatusAndSayingBySayingId(@Param("sayingId") Long sayingId, @Param("custId") String custId);
void remove(@Param("sayingId") Long sayingId);
void passSaying(@Param("sayingId") Long sayingId);
void add(Saying saying);
void increaseCommentNum(@Param("sayingId") Long sayingId);
void reduceCommentNum(@Param("sayingId") Long sayingId);
void increaseLikes(@Param("sayingId") Long sayingId);
void reduceLikes(@Param("sayingId") Long sayingId);
}
以上素材来自徐师兄之前做的一个类似QQ发说说的功能 功能还有二级评论点赞,简直个人crud巅峰操作
思考:这是mybatis单独使用的情况 使用的mybatis提供的原生API 没有spring的封装
1.4.1 通过mybatis API使用方式
/**
* @Description: 使用MyBatis API方式
* @Author create by xuchao
* @Date 2020/7/7 21:27
* @throws IOException
*/
@Test
public void testSessionApi() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// session里面封装了很多操作数据库的方法
SqlSession session = sqlSessionFactory.openSession();
try {
// 这里传的mapper的全路径 容易出错 编译时候无法发现错误 运行时候会找不到对应的mapper
Blog blog = (Blog) session.selectOne("com.qingshan.mapper.BlogMapper.selectBlogById", 1);
System.out.println(blog);
} finally {
session.close();
}
}
1.4.2 通过sql.session.getMapper(XXXMapper.class)
/**
* @Description: 通过 SqlSession.getMapper(XXXMapper.class) 接口方式
* @Author create by xuchao
* @Date 2020/7/7 21:34
* @throws IOException
*/
@Test
public void testSelect() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession(); // ExecutorType.BATCH
try {
// 这里虽然也是通过反射机制获取对应的mapper对应的方法 但是传的字节码对象 不容易出错!
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlogById(1);
System.out.println(blog);
} finally {
session.close();
}
}
2. Mybatis核心配置
点击进入mybatis中文官网
每一个标签其实都是对应源码里面的一个配置类
2.1 configuration根标签
大部分mybatis的配置都会有对应的默认值,所以最简单的配置是啥也不写就留一个根标签
2.2 properties标签
<!-- 对应我们properties配置文件当中 一般配置数据库的连接信息-->
<!-- 这个resource也可以是 URL-->
<!-- 直接修改我的配置文件 方便不同开发环境修改信息 而不需要编译重启项目-->
<properties resource="db.properties"></properties>
2.3 setting标签!
2.4 environments标签
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
2.5 typeAliases标签
<typeAliases>
<!-- 类型别名 类似spring里面bean的alias-->
<!-- 这样在使用的时候就不要全路径 写对应的别名就行 简化配置文件-->
<typeAlias alias="saying" type="com.xuchao.p5.Saying" />
</typeAliases>
2.6 typeHandlers标签
public class MyTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
// 设置 String 类型的参数的时候调用,Java类型到JDBC类型
// 注意只有在字段上添加typeHandler属性才会生效
// insertBlog name字段
System.out.println("---------------setNonNullParameter1:"+parameter);
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
// 根据列名获取 String 类型的参数的时候调用,JDBC类型到java类型
// 注意只有在字段上添加typeHandler属性才会生效
System.out.println("---------------getNullableResult1:"+columnName);
return rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
// 根据下标获取 String 类型的参数的时候调用
System.out.println("---------------getNullableResult2:"+columnIndex);
return rs.getString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
System.out.println("---------------getNullableResult3:");
return cs.getString(columnIndex);
}
}
<typeHandlers>
<!-- 使用自己编写的typeHandler-->
<typeHandler handler="com.xuchao.type.MyTypeHandler"></typeHandler>
</typeHandlers>
<!-- resultMap对应类型转换的时候使用 -->
<result column="name" property="name" jdbcType="VARCHAR" typeHandler="com.xuchao.type.MyTypeHandler"/>
2.7 objectFactory标签
每次 MyBatis 创建结果(结果集转化JAVA对象)对象的新实例时,它都会使用一个对象工厂(ObjectFactory)接口来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现
如果说自定义的对象工厂 在全局配置文件中配置之后 就可以了
/**
* <p>
* 自定义ObjectFactory,通过反射的方式实例化对象
* 一种是无参构造函数,一种是有参构造函数——第一个方法调用了第二个方法
*/
public class MyObjectFactory extends DefaultObjectFactory {
@Override
public Object create(Class type) {
System.out.println("--------------------调用了创建对象的方法:" + type);
if (type.equals(Blog.class)) {
Blog blog = (Blog) super.create(type);
blog.setName("object factory");
blog.setBid(1111);
blog.setAuthorId(2222);
return blog;
}
Object result = super.create(type);
return result;
}
}
<objectFactory type="com.xuchao.objectfactory.MyObjectFactory">
<property name="test" value="69"/>
</objectFactory>
2.8 mappers标签
2.8 resultMap!!
resultMap是mybatis最强大的标签 在这里重点介绍!!!
<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="唯一的标识" type="映射的pojo对象">
<id column="表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型" property="映射pojo对象的主键属性" />
<result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属
性)"/>
<association property="pojo中的一个对象属性" javaType="pojo中关联的对象">
<id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo对象的主键属性"/>
<result column="任意表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
</association>
<!-- 集合中的property须为oftype定义的pojo对象的属性-->
<collection property="pojo的集合属性" ofType="集合中的pojo对象">
<id column="集合中pojo对象对应的表的主键字段" jdbcType="字段类型" property="集合中pojo对象的主键属性" />
<result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" />
</collection>
</resultMap>
<strong>如果collection标签是使用嵌套查询,格式如下:</strong>
<collection column="传递给嵌套查询语句的字段参数" property="pojo对象中集合属性" ofType="集合属性中的pojo对象" select="嵌套的查询语句" >
</collection>