Mybatis框架

mac2024-07-29  54

文章目录

Mybatis日志介绍日志级别日志配置 ORM介绍Mybatis入门1.引入jar包2.实体类3.dao层4.主配置文件5.mapper配置文件 $和#的区别(重点)自定义工具类主键返回动态代理实现安装Free Mybatis plugin插件 多参数 转义<![CDATA[]]> 模糊查询动态Sql1.if2.where3.set4.trim5.choose when otherwise6.bind(如上)7.sql include8.foreach 数组 集合 resultMap一对一一对多延迟加载一二级缓存

Mybatis


日志介绍

日志级别

OFF<FATAL<ERROR<WARN<INFO<DEBUG<ALL

右边的级别包含左边的全部日志

日志配置
log4j.rootCategory=DEBUG, stdout , R log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n log4j.appender.R=org.apache.log4j.DailyRollingFileAppender log4j.appender.R.File=F://mybatis.log log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

ORM介绍

Orm框架:完成数据库表与Javabean对象关系映射的框架就叫orm框架

JDBC:过程太麻烦,orm框架对原始jdbc过程进行封装

常见orm框架

Mybatis:用得多Hibernate:用得少,学习成本高 40-50% 老的管理项目,趋于淘汰Springjdbc:(用得少)

Mybatis入门

原名ibatis

mybatis将java代码和sql语句解耦合,将sql语句嵌入到xml配置文件中

1.引入jar包
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency>
2.实体类
package cn.cdqf.entity; import java.io.Serializable; public class User implements Serializable { private String uname; private int uid; public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } @Override public String toString() { return "User{" + "uname='" + uname + '\'' + ", uid=" + uid + '}'; } }
3.dao层
public interface UserDao2 { List<User> queryAll(); User queryByName(@Param("uname") String uname); User queryByName2(@Param("user") User uname); void insert(@Param("user") User user); void insert2(@Param("user") User user); //根据名称模糊查询 根据年龄范围查询 List<User> queryByNameAndAge(@Param("uname") String uname,@Param("age") int age); } package cn.cdqf.dao.impl; import cn.cdqf.dao.UserDao; import cn.cdqf.entity.User; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; import java.util.List; public class UserDaoImpl implements UserDao { public List<User> queryAll() { //构造者模式 build :构建工厂 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //把配置文件转成输入流 InputStream resourceAsStream = UserDaoImpl.class.getResourceAsStream("/mybatis-config.xml"); //UserDaoImpl.class.getClassLoader().getResourceAsStream() //所有的构造者模式,有个方法build方法 //工厂模式:造类 创建对象 SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream); //拿数据库连接对象 connection mybatis改名为SqlSession SqlSession sqlSession = build.openSession(); List<User> objects = sqlSession.selectList("cn.cdqf.dao.UserDao.queryAll"); //关闭资源 sqlSession.close(); return objects; } }
4.主配置文件
<?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> </configuration> <?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="jdbc.properties"></properties> <typeAliases> <!--简写 实体类--> <package name="cn.cdqf.entity"></package> </typeAliases> <!--编码环境:Development、Test、Product--> <!-- prod:生产环境,真实上线 运维 test:测试环境 测试部门 dev:开发环境 开发 --> <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> <!--指定mapper配置文件--> <mapper resource="mapper/UserMapper.xml"/> </mappers> </configuration>
5.mapper配置文件
<?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.xml,一般用接口全路径来标识 --> <mapper namespace="cn.cdqf.dao.UserDao"> </mapper> <?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.xml,一般用接口全路径来标识 --> <mapper namespace="cn.cdqf.dao.UserDao"> <!-- id:对应接口中的方法名 id是唯一标识 不会重复 resultType:指定当前查询的返回值,返回值只需要指定集合里面的内容,mybatis会根据sql返回条数自动判断是集合还是单个对象 select:执行体 statement --> <select id="queryAll" resultType="cn.cdqf.entity.User"> select * from user_a </select> <!-- parameterType:指定参数类型 --> <select id="queryByName" resultType="User" parameterType="string"> <!--#{名字要跟接口方法中@param注解中指定名字相同} ......where uname=? preparedStatemenet:会把传递字符串参数来的参数加"" 预编译平台,防止sql注入 select * from user_a where uname="张三" "'张三' or 1=1"参数 delete from user_a where uname='张三' or 1=1 delete from user_a where uname="'张三' or 1=1" 预编译平台 --> select * from user_a where uname=#{uname} </select> <select id="queryByName2" resultType="user" parameterType="user"> <!-- $会直接取 传过来对象参数的属性 --> select * from user_a where uname='${uname}' </select> <insert id="insert" parameterType="user"> insert into user_a(uid,uname) values(#{uid},#{uname}) </insert> <!-- 插入的时候获得主键id 1.在insert标签 指定下面三个属性 useGeneratedKeys="true" keyColumn="uid":指定数据库字段 keyProperty="uid":java对象的字段 2.在insert内部加入如下代码 <selectKey keyProperty="uid" keyColumn="uid" resultType="int"> select last_insert_id(); </selectKey> --> <insert id="insert2" parameterType="user"> insert into user_a(uname) values(#{uname}) </insert> </mapper>

$和#的区别(重点)

取参数

#采用预编译方式,会将传入的字符串用双引号引起,防止sqk注入 直 接 将 值 取 出 , 不 能 防 止 s q l 注 入 , 而 且 直接将值取出,不能防止sql注入,而且 ,sql,只能接受对象参数

但若涉及到为sql传参以外的sql,如果需要java传递,就必须用**$**取

自定义工具类

package cn.cdqf.util; import cn.cdqf.dao.impl.UserDaoImpl; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public enum MyBatisUtil { INSTANCE;//就是当前类的对象 并且是单例 private static final SqlSessionFactory sqlSessionFactory; static{ //构造者模式 build :构建工厂 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //把配置文件转成输入流 InputStream resourceAsStream = UserDaoImpl.class.getResourceAsStream("/mybatis-config.xml"); //UserDaoImpl.class.getClassLoader().getResourceAsStream() //所有的构造者模式,有个方法build方法 //工厂模式:造类 创建对象 sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream); } //获取连接 public SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } //关闭连接 public void close(SqlSession sqlSession){ if(sqlSession!=null) sqlSession.close(); } //提交事务 public void commit(SqlSession sqlSession){ if(sqlSession!=null) sqlSession.commit();//重要,否则更新类型的sql无法同步到数据库 close(sqlSession); } //回滚事务 public void rollback(SqlSession sqlSession){ if(sqlSession!=null) sqlSession.rollback(); close(sqlSession); } }

主键返回

<!-- 插入的时候获得主键id --> 1.在insert标签 指定下面三个属性 useGeneratedKeys="true" keyColumn="uid":指定数据库字段 keyProperty="uid":java对象的字段 2.在insert内部加入如下代码 <selectKey keyProperty="uid" keyColumn="uid" resultType="int"> select last_insert_id(); </selectKey>

动态代理实现

必须满足的条件

通过公共接口调用mapper.xml中的namespace必须是接口的全限定名mapper.xml中的id必须和接口中的方法名一致
安装Free Mybatis plugin插件

多参数 转义<![CDATA[]]> 模糊查询

多个不同类型的参数,parameterType就不写

<select id="queryByNameAndAge" resultType="cn.cdqf.entity.User"> <![CDATA[ select * from user_a where uname like concat("%",#{uname},"%") and age < #{age} ]]> </select>

动态Sql

1.if
<!--判断名字不为null 且不为""--> <if test="uname!=null and uname!=''"> where uname like concat("%",#{uname},"%") </if> <if test="age!=null and age>0"> and age>#{age} </if>
2.where

自动去掉第一个and

<select id="selectUserByIdAndName" resultType="com.edu.entity.User"> select * from users <where> <if test="name!=null and name !=''"> and username like concat("%",#{name},"%") </if> <if test="id != 0"> and id > #{id} </if> </where> </select>
3.set

自动去掉最后一个","

<update id="update"> <if test="map != null"> update users <set> <foreach collection="map" index="key" item="value"> ${key} = #{value}, </foreach> </set> where id = #{id} </if> </update>
4.trim
<update id="update"> <if test="map != null"> update users <!--prefix:前缀 suffixOverrides:覆盖最后的标记--> <trim prefix="set" suffixOverrides=","> <foreach collection="map" index="key" item="value"> ${key} = #{value}, </foreach> </trim> where id = #{id} </if> </update>
5.choose when otherwise

互斥

<select id="selectUserByIdAndName" resultType="com.edu.entity.User"> <bind name="selectStr" value="'%'+name+'%'"/> select * from users <trim prefix="where" prefixOverrides="and"> <choose> <when test="name!=null and name !=''"> username like #{selectStr} </when> <otherwise> and id > #{id} </otherwise> </choose> </trim> </select>
6.bind(如上)
7.sql include
</select> <sql id="useSql"> users </sql> <select id="selectUserById" resultMap="UserMap" parameterType="int"> select * from <include refid="useSql"></include> where id = #{id} </select>
8.foreach 数组 集合
<update id="update"> <if test="map != null"> update users <trim prefix="set" suffixOverrides=","> <!--collection:接口中@Param定义的参数名 若未定义,array:数组,maps:Map --> <foreach collection="map" index="key" item="value"> ${key} = #{value}, </foreach> </trim> where id = #{id} </if> </update>

resultMap

<!-- 反射设置值,根据数据库列名 来获得属性名 1.改别名(跟属性名相同) cdqf_tid tid,cdqf_tname tname 2.通过resultMap映射 --> <resultMap id="baseMap" type="Teacher"> <!-- type="Teacher":属性类型 column:查询出来的列名 property:类中属性名 --> <id column="cdqf_tid" property="tid"></id> <result column="cdqf_tname" property="tname"></result> </resultMap> <sql id="baseSql"> cdqf_tid,cdqf_tname </sql> <select id="queryAll" resultMap="baseMap"> select <include refid="baseSql"></include> from cdqf_teacher </select>

一对一

连表查询

<resultMap id="baseMap" type="Student"> <id column="cdqf_sid" property="sid"></id> <result column="cdqf_sname" property="sname"></result> <!-- 映射一对一关系 property:属性名 javaType:当前属性的类型 --> <association property="teacher" javaType="Teacher"> <id column="cdqf_tid" property="tid"></id> <result column="cdqf_tname" property="tname"></result> </association> </resultMap> <select id="queryAll" resultMap="baseMap"> SELECT cdqf_sid,cdqf_sname,cdqf_tname,cdqf_tid FROM cdqf_student s JOIN cdqf_teacher t ON s.`tid`=t.`cdqf_tid` </select>

接口调用

<resultMap id="UserMap" type="user"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="tel" column="tel"/> <result property="createTime" column="createTime"/> <!--columu属性将参数传到调用的接口方法中执行查询--> <association property="power" column="power" javaType="Permission" select="com.edu.dao.PowerDao.queryPowerById" > </association> </resultMap> <select id="selectAll" resultMap="UserMap"> select * from users </select>

一对多

连表查询

<resultMap id="baseMap" type="Teacher"> <!-- type="Teacher":属性类型 column:查询出来的列名 property:类中属性名 --> <id column="cdqf_tid" property="tid"></id> <result column="cdqf_tname" property="tname"></result> <!--ofType:集合元素得类型 --> <collection property="studentList" ofType="Student"> <id column="cdqf_sid" property="sid"></id> <result column="cdqf_sname" property="sname"></result> </collection> </resultMap> <sql id="baseSql"> cdqf_tid,cdqf_tname </sql> <select id="queryAll" resultMap="baseMap"> SELECT cdqf_tid,cdqf_tname,cdqf_sid,cdqf_sname FROM cdqf_teacher t JOIN cdqf_student s ON t.`cdqf_tid`=s.`tid` </select>

接口调用

<resultMap id="Power" type="Permission"> <id property="id" column="id"/> <result property="right" column="right_value"/> <!--columu属性将参数传到调用的接口方法中执行查询--> <collection property="users" column="id" ofType="User" select="com.edu.dao.UserDao.selectUserById"> </collection> </resultMap> <select id="queryAllPower" resultMap="Power"> select * from permission </select>

延迟加载

<settings> <setting name ="aggressiveLazyLoading" value="false"/> <!--开启延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> </settings>

一二级缓存

<setting name="localCacheScope" value="SESSION"/> <setting name="cacheEnabled" value="true"/> <cache/>
最新回复(0)