public class MybatisTest { public static void main(String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("MyMapper.selectUser",1); System.out.println(user); } }
<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>
<!--配置全局属性--> <settings> <!-- 开启驼峰命名转换 :{name_id} -> {nameId} --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
在四大对象的建立过程当中都会有插件的介入;html
(1)useGeneratedKeys 和 keyProperty 属性配合使用便可获取到自增主键的值;java
(2)使用 selectkey 标签也能够实现,不过 order 的属性值要设置为 after 才能获取获得;mysql
<selectKey order="AFTER"keyProperty="id" resultType="String">select last_insert_id()</selectKey>
(1)在要执行的sql前用 selectKey 标签来实现;git
(2)相关的三个属性分别是 keyProperty、resultType 和 order;github
(3)有两种写法分别是 order 的属性值为 before 和 after;Oracle 用 before;web
<selectKey keyColumn="id" keyProperty="id" order="BEFORE" resultType="int"> select max(id)+1 as myNo from emp </selectKey>
<!--序列实现自增主键-->
SQL >create sequence autoID increment by 1 start with 1 maxvalue 999999 cycle;
SQL >insert into tablename values(autoID.nextval,...);
一、int、long 和 boolean 类型的返回值咱们能够直接用;spring
二、增删改后必定要 commit,不然对于数据库的修改不会生效;sql
<resultMap id="myuser" type="com.stan.hello.User"> <!--<id column="id" property="id"></id>--> <result column="user_name" property="userName"></result> </resultMap> <select id="queryUserById" resultMap="myuser" parameterType="java.lang.String"> select * from tb_user where id = #{id} </select>
(1)OGNL(对象图导航语言):数据库
(2)if 判断编程
<select id="queryUserList" resultType="com.stan.pojo.User"> select * from tb_user WHERE 1=1 <if test="name!=null and name.trim()!=''"> and name like '%${name}%' </if> </select>
<!--if 判断拼接 where 条件存在多余 and 的解决方法:加一个 1=1;使用where 或者 trim标签;-->
(1)语法:choose----when----when----otherwise-----choose;
(2)理解:相似于 java 中带break 的 switch语句,只匹配一个条件;
<select id="queryUserByNameOrAge" resultType="com.stan.pojo.User"> select * from tb_user WHERE 1=1 <choose> <when test="name!=null and name.trim()!=''"> and name like '%${name}%' </when> <when test="age!=null"> and age = #{age} </when> <otherwise> and name='allen' </otherwise> </choose> </select>
(1)遍历集合拼接 where 条件(如:in 集合):几个经常使用的属性 collection、item、separator、open、close、index(map的key)
List<User> queryUserByIds(@Param("ids") String[] ids); <select id="queryUserByIds" resultType="com.stan.pojo.User"> select * from tb_user where id in <foreach collection="ids" item="id" open="(" close=")" separator=","> #{id} </foreach> </select>
(2)数据批量插入
<select id="queryUserByNameAndAge" resultType="com.stan.pojo.User"> select * from tb_user <where> <if test="name!=null and name.trim()!=''"> and name like '%${name}%' </if> <if test="age!=null"> and age = #{age} </if> </where> </select>
<update id="updateUser"> update tb_user <set> <if test="userName != null and userName.trim() != ''"> user_name=#{userName} </if> <if test="password != null and password.trim() != ''"> password=#{password} </if> </set> where id = #{id} </update>
update tb_user <trim prefix="set" suffixoverride="," suffix=" where id = #{id} "> <if test="userName != null and userName.length()>0"> user_name=#{userName} , </if> <if test="password != null and password.length()>0"> password=#{password} , </if> </trim>
<select id="getEmpsTestInnerParameter" resultType="com.hand.mybatis.bean.Employee"> <bind name="bindeName" value="'%'+userName+'%'"/> SELECT * FROM tb_user <if test="userName!=null"> where user_name like #{bindeName} </if> </select>
(1)内置参数:
(2)sql 片断:
<sql id="commonSql">id,user_name,password</sql> <select id="queryUserById" resultMap="userResultMap"> select <include refid="commonSql"></include> from tb_user where id = #{id} </select>
(1)做用:就是提高查询的效率;
(2)分类:
(1)一级缓存失效的四种状况
(1)做用:能够实现不一样的 session 之间的数据共享,一个 namespace(一个接口)对应一个map(二级缓存);
(2)原理:
(3)使用:
(1)缓存相关设置
(2)原理图示
(1)导入缓存的包和整合包;测试的时候采用的maven
<dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.5</version> </dependency>
(2)classpath 下编写 ehcache-xml 配置文件;
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"> <diskStore path="D:\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
(3)打开二级缓存的总开关,直接在mapper xml 中用 cache 标签引用;
<cache type="org.mybatis.caches.ehcache.EhcacheCache" > <property name="timeToIdleSeconds" value="3600"/> <property name="timeToLiveSeconds" value="3600"/> <property name="maxEntriesLocalHeap" value="1000"/> <property name="maxEntriesLocalDisk" value="10000000"/> <property name="memoryStoreEvictionPolicy" value="LRU"/> </cache>
(4)另外一个 mapper 能够用 cache-ref 标签来引用其余 mapper 的缓存策略;
<cache-ref namespace="com.stan.crud.UserDaoMapper"/>
(5)相关配置参数的说明
diskStore标签:指定数据在磁盘中的存储位置。 defaultCache标签:当借助CacheManager.add("demoCache")建立Cache时,EhCache便会采用<defalutCache/>指定的的管理策略 如下属性是必须的: maxElementsInMemory - 在内存中缓存的element的最大数目 maxElementsOnDisk - 在磁盘上缓存的element的最大数目,如果0表示无穷大 eternal - 设定缓存的elements是否永远不过时。若是为true,则缓存的数据始终有效,若是为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断 overflowToDisk - 设定当内存缓存溢出的时候是否将过时的element缓存到磁盘上 如下属性是可选的: timeToIdleSeconds - 当缓存在EhCache中的数据先后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大 timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大 diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每一个Cache都应该有本身的一个缓冲区. diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。 diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每一个120s,相应的线程会进行一次EhCache中数据的清理工做 memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
一、具体的代码和数据库脚本参考:https://blog.csdn.net/hellozpc/article/details/80878563#12_1741
<resultMap id="orderUserRM" type="com.stan.pojo.OrderUser" autoMapping="true"> <association property="user" javaType="com.stan.pojo.User" autoMapping="true"> <id property="id" column="user_id"></id> </association> </resultMap> <select id="queryOrderUserByOrderNumber" resultMap="orderUserRM" parameterType="String"> select * from tb_order o left join tb_user u on o.user_id = u.id where o.order_number = #{number} </select>
<resultMap id="orderUserRM" type="com.stan.pojo.OrderUser" autoMapping="true"> <association property="user" javaType="com.stan.pojo.User" autoMapping="true"> <id property="id" column="user_id"></id> </association> <collection property="details" autoMapping="true" javaType="list" ofType="com.stan.pojo.OrderDetail" >
<!--这里的 OrderDetail 是订单和商品关系的媒介--> <id property="id" column="detial_id"></id> <association property="item" javaType="com.stan.pojo.Item" autoMapping="true"> <id property="id" column="item_id"></id> </association> </collection> </resultMap> <select id="queryOrderItemByOrderNumber" resultMap="orderUserRM2" parameterType="String"> select *,d.id as detial_id from tb_order o left join tb_user u on o.user_id = u.id left join tb_orderdetail d on o.id = d.order_id left join tb_item i on i.id = d.item_id where o.order_number = #{number} </select>
<!--延迟加载关联查询总开关,association和collection标签里的fetchType也是设置加载的模式的--> <setting name="lazyLoadingEnabled" value="true"/> <!--设置为true的话,只要get一个关联的属性,全部的关联查询都会发出--> <setting name="aggressiveLazyLoading" value="false"/>
<resultMap id="rm2" type="com.stan.pojo.OrderUser" autoMapping="true"> <association property="user" javaType="com.stan.pojo.User" autoMapping="true" select="queryUserById" column="user_id">
<!--这里的select指定关联的查询的 id,这里的column是传过去的参数-->
<!--多个参数的传递能够用map,就是这样的形式:{key1=col1,key2=col2}-->
</association> </resultMap> <select id="queryOrderByNumber" resultMap="rm2"> select * from tb_order where order_number = #{number} </select>
<!--这个方法不单独使用的话能够不在 mapper 接口中书写方法定义--> <select id="queryUserById" resultType="com.stan.pojo.User"> select * from tb_user where id = #{number} </select>
OrderUser queryOrderByNumber(@Param("number") String number);
@Test public void queryOrderByNumber() throws IOException { OrderMapper mapper = sqlSession.getMapper(OrderMapper.class); OrderUser orderUser = mapper.queryOrderByNumber("201807010001"); System.out.println("----------------------"); System.out.println(orderUser.getOrderNumber()); System.out.println("--------------------"); System.out.println(orderUser.getUser()); }
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.1</version> </dependency>
(1)核心包:spring包、springmvc包、mybatis包、spring-mybatis整合包
(2)其余包:日志包、链接池包
(1)主要就是配全局 settings 等;
(1)controller 扫描;
(2)视图解析器;
(3)注解驱动;
(4)默认servlet 处理;
(1)包扫描;
(2)数据源的配置;
(3)事务管理(基于注解的事务);
(4)sqlSessionFactory配置;
(5)配置能够批量执行的 sqlSession;
(6)配置Mapper 接口的扫描(不可少);
(1)全局参数配置 spring配置文件的路径;
(2)配置spring 监听;
(3)配置 springmvc 的DispatcherServlet;
(4)spring框架会自动加载 web-inf 下的配置文件,classpath 路径下的配置文件须要配置路径;
(5)SSM框架整合示例;
(1)导包
(2)配置文件(mbg.xml)
(3)运行生成器 java 代码
EmployeeExample example = new EmployeeExample(); Criteria criteria = example.createCriteria(); criteria.andLastNameLike("%e%"); criteria.andGenderEqualTo("1"); Criteria criteria2 = example.createCriteria(); criteria2.andEmailLike("%e%"); example.or(criteria2);
(1)原理
(2)简单实现:单个插件
(3)多个插件:拦截同一个对象同一个方法
(4)开发示例:
@Intercepts({@Signature(type= ParameterHandler.class,method = "setParameters",args = {PreparedStatement.class})}) public class MyIntercepter implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { System.out.println("要拦截的方法:"+invocation.getMethod()); MetaObject metaObject = SystemMetaObject.forObject(invocation.getTarget()); Object para = metaObject.getValue("parameterObject"); System.out.println("原来的参数是:"+para); metaObject.setValue("parameterObject","5"); return invocation.proceed(); } public Object plugin(Object o) { System.out.println("包装的对象:"+o.toString()); return Plugin.wrap(o,this); } public void setProperties(Properties properties) { System.out.println(properties.getProperty("test")); } }
(5)PageHelper 插件使用:实现查询数据的分页功能
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.1.4</version> </dependency>
<plugins> <plugin interceptor="com.github.pagehelper.PageHelper"> <property name="dialect" value="mysql"/> <property name="offsetAsPageNum" value="false"/> <property name="rowBoundsWithCount" value="false"/> <property name="pageSizeZero" value="true"/> <property name="reasonable" value="false"/> <property name="supportMethodsArguments" value="false"/> <property name="returnPageInfo" value="none"/> </plugin> </plugins>
<select id="queryUserPage" resultType="com.stan.pojo.User"> select * from tb_user </select>
public List<User> queryUserPage();
@Test public void queryPage() throws IOException { Page<User> page = PageHelper.startPage(2,4); List<User> users = mapper.queryUserPage(); for (User user : users) { System.out.println(user); } System.out.println(page); }
(1)批量执行sql语句
(2)mybatis 调用存储过程:示例参考
(3)自定义类型处理器处理枚举类型
一、枚举类型
二、自定义类型处理器:参考示例