Mybatis学习笔记
2019-09-17 10:19:32来源:博客园 阅读 ()
时间:2019-09-10
一、Maven环境搭建
1.导入jar坐标
1 <dependencies> 2 <dependency> 3 <groupId>junit</groupId> 4 <artifactId>junit</artifactId> 5 <version>4.11</version> 6 <scope>test</scope> 7 </dependency> 8 9 <dependency> 10 <groupId>org.mybatis</groupId> 11 <artifactId>mybatis</artifactId> 12 <version>3.4.5</version> 13 </dependency> 14 15 <dependency> 16 <groupId>log4j</groupId> 17 <artifactId>log4j</artifactId> 18 <version>1.2.12</version> 19 </dependency> 20 21 <dependency> 22 <groupId>mysql</groupId> 23 <artifactId>mysql-connector-java</artifactId> 24 <version>5.1.32</version> 25 </dependency> 26 <dependencies>
2.db.properties数据库连接配置(根据个人具体情况书写)
1 jdbc.driver=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:3307/user 3 jdbc.username=root 4 jdbc.password=root
3.创建目录结构
4.创建数据库表
①emp
②dep
二、配置文件
1.全局配置文件mybatis-config.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 6 <!-- 自动代码提示设置 --> 7 <!-- preferences→XMLCatlog→add(Location=本地文件路径,KeyType=UID,Key=上面连接) --> 8 <!-- 全局配置文件(前后顺序需要按照规定来) --> 9 <configuration> 10 <!-- 属性配置 --> 11 <!-- resource="src类路径下配置文件名" --> 12 <!-- uri="网络路径路径下配置文件名" --> 13 <properties resource="db.properties"> 14 <!-- name="k" --> 15 <!-- value="v" --> 16 <property name="k" value="v" /> 17 </properties> 18 19 <!-- 设置配置 --> 20 <settings> 21 <!-- 内容过多,详细参考官方文档 http://www.mybatis.org/mybatis-3 --> 22 <!-- 开启缓存机制 --> 23 <setting name="cacheEnabled" value="true" /> 24 <!-- 开启延迟加载 --> 25 <setting name="lazyLoadingEnabled" value="true" /> 26 <!-- 关闭主动延迟加载,即按照需求进行延迟加载 --> 27 <setting name="aggressiveLazyLoading" value="false" /> 28 </settings> 29 30 <!-- 别名设置 --> 31 <typeAliases> 32 <!-- type="java全限定类名" --> 33 <!-- alias="别名(默认为类名,不区分大小写)" --> 34 <typeAlias type="com.panda.beans.Emp" alias="Emp" /> 35 <!-- 为整个包下的类取别名(类名),有重复则对重复部分单独命名 --> 36 <package name="com.panda.beans" /> 37 </typeAliases> 38 39 <!-- 环境配置 --> 40 <!-- default="默认id对应的数据库配置环境" --> 41 <environments default="mysql"> 42 <!-- 与default对应 --> 43 <environment id="mysql"> 44 <!-- 事务管理器 --> 45 <!-- "JDBC", JdbcTransactionFactory.class --> 46 <!-- Spring解决 --> 47 <transactionManager type="JDBC" /> 48 <!-- 数据源 --> 49 <!-- "POOLED", PooledDataSourceFactory.class --> 50 <!-- "UNPOOLED", UnpooledDataSourceFactory.class --> 51 <!-- "JNDI", JndiDataSourceFactory.class --> 52 <!-- Spring解决 --> 53 <dataSource type="POOLED"> 54 <!-- 数据库配置信息 --> 55 <property name="driver" value="${jdbc.driver}" /> 56 <property name="url" value="${jdbc.url}" /> 57 <property name="username" value="${jdbc.username}" /> 58 <property name="password" value="${jdbc.password}" /> 59 </dataSource> 60 </environment> 61 </environments> 62 63 <!-- 映射配置 --> 64 <mappers> 65 <!-- resource="src类路径下配置文件名" --> 66 <!-- uri="网络路径路径下配置文件名" --> 67 <!-- class="注解时指定dao全限定类路径" --> 68 <!-- <mapper resource="EmpDao.xml" /> 适用于单个测试 --> 69 <!-- <mapper resource="com/panda/dao/EmpDao.xml" /> --> 70 <!-- package=dao(接口类存放包) --> 71 <!-- 注意:1.使用package时config文件和dao文件必须同目录同名存放(平行包结构) --> 72 <package name="com.panda.dao" /> 73 </mappers> 74 </configuration>
2.Sql配置文件EmpDao.xml(非动态sql)
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <!-- 自动代码提示设置 --> 7 <!-- preferences→XMLCatlog→add(Location=本地文件路径,KeyType=UID,Key=上面连接) --> 8 <!-- namespace为dao/mapper全限定路径 --> 9 <mapper namespace="com.panda.dao.EmpDao"> 10 <!-- id对应接口里的方法名 --> 11 <!-- parameterType对应传入参数类型,可以省略Mybatis自行推断 --> 12 <!-- resultType对应返回值类型,当返回集合时,返回值类型为集合中的单个对象类型 --> 13 <!-- 使用insert,update,delete时候需要selSession.commite() --> 14 15 <!-- 逻辑运算符的书写规则 --> 16 <!-- 原符号 < <= > >= & ' " --> 17 <!-- 替换符号 < <= > >= & ' " --> 18 19 <!-- 获取参数方式1:#{}预编译sql --> 20 <!-- 获取参数方式2:${}拼接sql,存在sql注入问题 --> 21 <!-- 原生jdbc不支持占位符的地方(选取字段,表名,条件字段)必须使用${} --> 22 23 <!-- type:结果最终封装类型 --> 24 <!-- id: 连接resultMap属性的唯一标识符 --> 25 <resultMap type="com.panda.beans.Emp" id="empAndDepResultMap"> 26 <!-- id:主键的特殊写法 --> 27 <!-- result:非主键的通用写法 --> 28 <!-- property:pojo对应成员变量名 --> 29 <!-- column:数据库表对应字段名 --> 30 <id property="id" column="eid" /> 31 <result property="name" column="name" /> 32 <result property="email" column="email" /> 33 <result property="gender" column="gender" /> 34 <!-- 一般级联方式 --> 35 <!-- <result property="dep.id" column="did" /> --> 36 <!-- <result property="dep.dep_name" column="dep_name" /> --> 37 <!-- association联合方式 --> 38 <!-- 结果为单条时使用association方式 --> 39 <!-- 子类型使用javaType --> 40 <!-- javaType为子查询对象 --> 41 <association property="dep" javaType="com.panda.beans.Dep"> 42 <id property="id" column="did" /> 43 <result property="dep_name" column="dep_name" /> 44 </association> 45 </resultMap> 46 <!-- 通过Id获取单个Emp对象级联dep对象使用resultMap --> 47 <!-- public Emp getEmpAndDepByIdUseResultMap(Integer id); --> 48 <select id="getEmpAndDepByIdUseResultMap" resultMap="empAndDepResultMap"> 49 select e.id as eid,e.name,e.email,e.gender,d.id as did,d.dep_name from emp as e,dep as d where e.dep_id=d.id and e.id=#{id} 50 </select> 51 52 53 <!-- 通过Id获取单个Emp对象级联dep对象使用associate分步查询 --> 54 <!-- public Dep getDepById(Integer id); --> 55 <select id="getDepById" resultType="com.panda.beans.Dep"> 56 select * from dep where id=#{id} 57 <!-- 多参传入时 --> 58 <!-- select * from dep where id=#{k1,k2} --> 59 </select> 60 <resultMap type="com.panda.beans.Emp" id="empAndDepStep"> 61 <id property="id" column="id" /> 62 <result property="name" column="name" /> 63 <result property="email" column="email" /> 64 <result property="gender" column="gender" /> 65 <!-- 分步查询 --> 66 <!-- fetchType="eager" 取消该查询的延迟加载 --> 67 <association property="dep" select="com.panda.dao.EmpDao.getDepById" column="dep_id"> 68 <!-- 多参传入时 --> 69 <!-- <association property="dep" select="com.panda.dao.EmpDao.getDepById" column="{k1=dep_id,k2=?}"> --> 70 <!-- 无需查询语句自动调用com.panda.dao.EmpDao.getDepById --> 71 </association> 72 </resultMap> 73 <!-- public Emp getEmpAndDepByIdUseStep(); --> 74 <select id="getEmpAndDepByIdUseStep" resultMap="empAndDepStep"> 75 select * from emp where id=#{id} 76 </select> 77 78 79 <!-- 通过Id获取Dep对象及其下属子集Emp --> 80 <!-- public Dep getDepAndEmpsByIdUseCollection(); --> 81 <!-- type为子查询对象 --> 82 <resultMap type="com.panda.beans.Dep" id="depAndEmpsCollection"> 83 <id property="id" column="did" /> 84 <result property="dep_name" column="dep_name" /> 85 <!-- 结果为多条时使用collection方式 --> 86 <!-- 集合类型使用ofType --> 87 <!-- ofType为子查询对象 --> 88 <collection property="emps" ofType="com.panda.beans.Emp"> 89 <id property="id" column="eid" /> 90 <result property="name" column="name" /> 91 <result property="mail" column="mail" /> 92 <result property="gender" column="gender" /> 93 </collection> 94 </resultMap> 95 <select id="getDepAndEmpsByIdUseCollection" resultMap="depAndEmpsCollection"> 96 select d.id as did,d.dep_name,e.id as eid,e.name,e.email,e.gender from dep as d left outer join emp as e on e.dep_id=d.id where d.id=#{id} 97 </select> 98 99 100 <!-- 通过did获取Emp对象集合 --> 101 <!-- public List<Emp> getEmpsByDep_Id(Integer id); --> 102 <select id="getEmpsByDep_Id" resultType="com.panda.beans.Emp"> 103 select * from emp where dep_id=#{did} 104 </select> 105 <!-- 通过Id获取单个Dep对象级联Emps对象集使用collection分步查询 --> 106 <!-- public Dep getDepAndEmpsByIdUseStep(Integer id); --> 107 <resultMap type="com.panda.beans.Dep" id="depAndEmpsStep"> 108 <id property="id" column="id" /> 109 <result property="dep_name" column="dep_name" /> 110 <!-- 分步查询 --> 111 <collection property="emps" select="com.panda.dao.EmpDao.getEmpsByDep_Id" column="id"> 112 <!-- 无需查询语句自动调用com.panda.dao.EmpDao.getEmpsByDep_Id --> 113 </collection> 114 </resultMap> 115 <select id="getDepAndEmpsByIdUseStep" resultMap="depAndEmpsStep"> 116 select * from dep where id=#{id} 117 </select> 118 119 120 <!-- public List<Emp> getEmps(); --> 121 <select id="getEmps" resultType="com.panda.beans.Emp"> 122 select * from emp 123 </select> 124 125 126 <!-- 赋值变量格式为 var=#{var} --> 127 <!-- public Emp getEmpById(Integer id); --> 128 <!-- 1.普通单参传递#{名字任意} --> 129 <!-- 当返回集合时,返回值类型为集合中的单个对象类型 --> 130 <select id="getEmpById" resultType="com.panda.beans.Emp"> 131 select * from emp where id=#{id} 132 </select> 133 134 135 <!-- public void insertEmp(Emp emp); --> 136 <!-- useGeneratedKeys="true" 取出执行行的自增id号 --> 137 <!-- keyProperty="id" 将取出的id号保存在参数列表中对象的id属性中 --> 138 <insert id="insertEmp" parameterType="com.panda.beans.Emp" useGeneratedKeys="true" keyProperty="id"> 139 insert into emp (name,email,gender) values(#{name},#{email},#{gender}) 140 </insert> 141 142 143 <!-- public void updateEmp(Emp emp); --> 144 <!-- 3.通过传入POJO,单参时直接#{property1,...propertyn} --> 145 <update id="updateEmp" parameterType="com.panda.beans.Emp"> 146 update emp set name=#{name} where id=#{id} 147 </update> 148 149 150 <!-- public void deleteEmpById(Integer id); --> 151 <delete id="deleteEmpById" parameterType="integer"> 152 delete from emp where id=#{id} 153 </delete> 154 155 156 <!-- public Emp getEmpByIdAndName(Integer id,String name); --> 157 <!-- 2.多个参数传递#{arg0/param0}...#{argn/paramn} --> 158 <select id="getEmpByIdAndName" resultType="com.panda.beans.Emp"> 159 select * from emp where id=#{arg0} and name=#{arg1} 160 </select> 161 162 163 <!-- getEmpByIdAndNameByAtParam(@Param("id") Integer id,..., @Param("name") String name); --> 164 <!-- 5.通过使用命名参数,#{id,...name} --> 165 <select id="getEmpByIdAndNameByAtParam" resultType="com.panda.beans.Emp"> 166 select * from emp where id=#{id} and name=#{name} 167 </select> 168 169 170 <!-- public Emp getEmpByIdAndNameByMap(Map<String, Object> map); --> 171 <!-- 4.通过传入Map时,直接使用map的K值类似于POJO#{k1,...kn} --> 172 <select id="getEmpByIdAndNameByMap" resultType="com.panda.beans.Emp"> 173 select * from emp where id=#{id} and name=#{name} 174 </select> 175 176 177 <!-- 通过id查询一条结果并封装成Map --> 178 <!-- public Map<String, Object> getEmpByIdReturnMap(Integer id); --> 179 <!-- 返回值类型直接写map,底层封装原理:K=数据库字段名,V=数据库的取值 --> 180 <select id="getEmpByIdReturnMap" resultType="map"> 181 select * from emp where id=#{id} 182 </select> 183 184 185 <!-- @MapKey("id") --> 186 <!-- public Map<String, Emp> getEmpsByIdReturnMap(Integer id); --> 187 <select id="getEmpsByIdReturnMap" resultType="com.panda.beans.Emp"> 188 <include refid="sql_template1"></include> 189 where id < #{id} 190 </select> 191 192 193 <!-- 抽取sql语句片段通过<include>调用 --> 194 <sql id="sql_template1">select * from emp</sql> 195 </mapper>
3.Sql配置文件EmpDynamicSqlDao.xml(动态sql)
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.panda.dao.EmpDynamicSqlDao"> 6 <!-- //ifwhere多条件动态sql查询Emps集 --> 7 <!-- 解决第一个出现and/or的问题 --> 8 <!-- public List<Emp> getEmpsByConditionIfWhere(Emp condition); --> 9 <select id="getEmpsByConditionIfWhere" resultType="com.panda.beans.Emp"> 10 select id,name,email,gender from emp 11 <where> 12 <if test="id!=null"> 13 and id=#{id} 14 </if> 15 <!-- 使用OGNL表达式 --> 16 <if test="name!=null and name.trim()!=''"> 17 and name=#{name} 18 </if> 19 <!-- 使用转义字符 --> 20 <if test="email!=null&&email.trim()!="""> 21 and email=#{email} 22 </if> 23 <!-- 使用外层单引号,内层双引号可以避免'男'被识别为char类型的 --> 24 <!-- 使用转义符,较麻烦 --> 25 <!-- 使用'男'.toString() --> 26 <if test='gender=="男" or gender=="女" '> 27 and gender=#{gender} 28 </if> 29 </where> 30 </select> 31 32 33 <!-- //iftrim多条件动态sql查询Emps集 --> 34 <!-- public List<Emp> getEmpsByConditionIfTrim(Emp condition); --> 35 <select id="getEmpsByConditionIfTrim" resultType="com.panda.beans.Emp"> 36 select id,name,email,gender from emp 37 <!-- 加前缀where,覆盖或者删除后缀and|or --> 38 <trim prefix="where" suffixOverrides="and|or"> 39 <if test="id!=null"> 40 id=#{id} and 41 </if> 42 <if test="name!=null and name.trim()!=''"> 43 name=#{name} and 44 </if> 45 <if test="email!=null&&email.trim()!="""> 46 email=#{email} and 47 </if> 48 <if test='gender=="男" or gender=="女" '> 49 gender=#{gender} 50 </if> 51 </trim> 52 </select> 53 54 55 <!-- //choose多条件逐一判断动态sql查询Emps值 --> 56 <!-- public List<Emp> getEmpsByConditionChoose(Emp condition); --> 57 <select id="getEmpsByConditionChoose" resultType="com.panda.beans.Emp"> 58 select id,name,email,gender from emp 59 where 60 <choose> 61 <when test="id!=null"> 62 id=#{id} 63 </when> 64 <when test="name!=null"> 65 name=#{name} 66 </when> 67 <when test="email!=null"> 68 email=#{email} 69 </when> 70 <otherwise> 71 gender="男" 72 </otherwise> 73 </choose> 74 </select> 75 76 77 <!-- //foreach查询几个Emps集 --> 78 <!-- public List<Emp> getEmpsByIdsForeach(@Param("ids")List<Integer> ids); --> 79 <select id="getEmpsByIdsForeach" resultType="com.panda.beans.Emp"> 80 select * from emp where id in 81 ( 82 <foreach collection="ids" item="id" open="" close="" separator=","> 83 #{id} 84 </foreach> 85 ) 86 </select> 87 88 89 <!-- //set多条件动态sql设置Emp值 --> 90 <!-- public void updateEmpByConditionIfSet(Emp condition); --> 91 <!-- 解决set后的多余,问题 --> 92 <update id="updateEmpByConditionIfSet"> 93 update emp 94 <set> 95 <if test="name!=null and name.trim()!=''"> 96 name=#{name}, 97 </if> 98 <if test="email!=null&&email.trim()!="""> 99 email=#{email}, 100 </if> 101 <if test='gender=="男" or gender=="女" '> 102 gender=#{gender} 103 </if> 104 </set> 105 where id=#{id} 106 </update> 107 108 109 <!-- //foreach批量添加Emps --> 110 <!-- public void insertLotEmps(@Param("emps") List<Emp> emps); --> 111 <insert id="insertLotEmps"> 112 insert into emp(name,email,gender) values 113 <foreach collection="emps" item="emp" open="" close="" separator=","> 114 (#{emp.name},#{emp.email},#{emp.gender}) 115 </foreach> 116 </insert> 117 118 119 <!-- 批量删除思路:delete from emp where id in() --> 120 <!-- 批量修改思路:update emp set name=#{name}...where id=#{id}(数据库连接url后面连接?allowMutilQueries=true) --> 121 </mapper>
三、创建dao和beans
1.EmpDao.java
1 package com.panda.dao; 2 /** 3 @author Jpanda 4 */ 5 6 import java.util.List; 7 import java.util.Map; 8 9 import org.apache.ibatis.annotations.MapKey; 10 import org.apache.ibatis.annotations.Param; 11 12 import com.panda.beans.Dep; 13 import com.panda.beans.Emp; 14 15 public interface EmpDao { 16 // 获取全体Emp对象 17 public List<Emp> getEmps(); 18 19 // 通过Id获取单个Emp对象 20 public Emp getEmpById(Integer id); 21 22 // 增加新员工 23 public void insertEmp(Emp emp); 24 25 // 修改员工信息 26 public void updateEmp(Emp emp); 27 28 // 删除员工 29 public void deleteEmpById(Integer id); 30 31 // 通过id和name获取单个Emp对象 32 public Emp getEmpByIdAndName(Integer id, String name); 33 34 // 通过id和name获取单个Emp对象使用命名参数 35 public Emp getEmpByIdAndNameByAtParam(@Param("id") Integer id, @Param("name") String name); 36 37 // 通过id和name获取单个Emp对象使用Map 38 public Emp getEmpByIdAndNameByMap(Map<String, Object> map); 39 40 // 通过id查询一条结果并封装成Map 41 public Map<String, Object> getEmpByIdReturnMap(Integer id); 42 43 // 通过id条件查询多条结果并封装成Map 44 @MapKey("id") 45 public Map<Integer, Emp> getEmpsByIdReturnMap(Integer id); 46 47 // 通过Id获取单个Emp对象级联dep对象使用resultMap 48 public Emp getEmpAndDepByIdUseResultMap(Integer id); 49 50 // 通过id查询获取单个Dep对象 51 public Dep getDepById(Integer id); 52 53 // 通过Id获取单个Emp对象级联dep对象使用associate分步查询 54 public Emp getEmpAndDepByIdUseStep(Integer id); 55 56 // 通过Id获取Dep对象及其下属子集Emp 57 public Dep getDepAndEmpsByIdUseCollection(Integer id); 58 59 // 通过did获取Emp对象集合 60 public List<Emp> getEmpsByDep_Id(Integer did); 61 62 // 通过Id获取单个Dep对象级联Emps对象集使用collection分步查询 63 public Dep getDepAndEmpsByIdUseStep(Integer id); 64 65 }
2.EmpDynamicSqlDao.java
1 package com.panda.dao; 2 3 import java.util.List; 4 5 import org.apache.ibatis.annotations.Param; 6 7 import com.panda.beans.Emp; 8 9 /** 10 * @author Jpanda 11 */ 12 public interface EmpDynamicSqlDao { 13 // ifwhere多条件动态sql查询Emps集 14 public List<Emp> getEmpsByConditionIfWhere(Emp condition); 15 16 // iftrim多条件动态sql查询Emps集 17 public List<Emp> getEmpsByConditionIfTrim(Emp condition); 18 19 // choose多条件逐一判断动态sql查询Emps值 20 public List<Emp> getEmpsByConditionChoose(Emp condition); 21 22 // foreach查询几个Emps集 23 public List<Emp> getEmpsByIdsForeach(@Param("ids") List<Integer> ids); 24 25 // set多条件动态sql设置Emp值 26 public void updateEmpByConditionIfSet(Emp condition); 27 28 // foreach批量添加Emps 29 public void insertLotEmps(@Param("emps") List<Emp> emps); 30 31 }
3.Emp.java
1 package com.panda.beans; 2 /** 3 @author Jpanda 4 */ 5 public class Emp { 6 private Integer id; 7 private String name; 8 private String email; 9 private String gender; 10 private Dep dep; 11 public Integer getId() { 12 return id; 13 } 14 public void setId(Integer id) { 15 this.id = id; 16 } 17 public String getName() { 18 return name; 19 } 20 public void setName(String name) { 21 this.name = name; 22 } 23 public String getEmail() { 24 return email; 25 } 26 public void setEmail(String email) { 27 this.email = email; 28 } 29 public String getGender() { 30 return gender; 31 } 32 public void setGender(String gender) { 33 this.gender = gender; 34 } 35 public Dep getDep() { 36 return dep; 37 } 38 public void setDep(Dep dep) { 39 this.dep = dep; 40 } 41 @Override 42 public String toString() { 43 return "Emp [id=" + id + ", name=" + name + ", email=" + email + ", gender=" + gender + ", dep=" + dep + "]"; 44 } 45 public Emp(Integer id, String name, String email, String gender, Dep dep) { 46 super(); 47 this.id = id; 48 this.name = name; 49 this.email = email; 50 this.gender = gender; 51 this.dep = dep; 52 } 53 public Emp() { 54 super(); 55 } 56 57 58 }
4.Dep.java
1 package com.panda.beans; 2 3 import java.util.List; 4 5 /** 6 @author Jpanda 7 */ 8 public class Dep { 9 private int id; 10 private String dep_name; 11 private List<Emp> emps; 12 public int getId() { 13 return id; 14 } 15 public void setId(int id) { 16 this.id = id; 17 } 18 public String getDep_name() { 19 return dep_name; 20 } 21 public void setDep_name(String dep_name) { 22 this.dep_name = dep_name; 23 } 24 public List<Emp> getEmps() { 25 return emps; 26 } 27 public void setEmps(List<Emp> emps) { 28 this.emps = emps; 29 } 30 @Override 31 public String toString() { 32 return "Dep [id=" + id + ", dep_name=" + dep_name + ", emps=" + emps + "]"; 33 } 34 35 36 }
四、执行测试类(学习的时候都复制第一个测试方法所以没有封装重复部分,能够理解就好,测试顺序也没有做到和sql配置文件顺序完全对应,懒得改了。。。。)
1.MybatisTest.java(非动态部分)
1 package com.panda.test; 2 3 import java.io.InputStream; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 import org.apache.ibatis.io.Resources; 9 import org.apache.ibatis.session.SqlSession; 10 import org.apache.ibatis.session.SqlSessionFactory; 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 import org.junit.BeforeClass; 13 import org.junit.Test; 14 15 import com.panda.beans.Dep; 16 import com.panda.beans.Emp; 17 import com.panda.dao.EmpDao; 18 19 /** 20 * @author Jpanda 21 */ 22 public class MybatisTest { 23 24 @BeforeClass 25 public static void setUpBeforeClass() throws Exception { 26 } 27 28 // 原始方法实现Mybatis 29 @Test 30 public void testHelloWorld() throws Exception { 31 // 通过流获取主配置文件 32 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 33 // 获取SqlSession工厂对象 34 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 35 // 获取sqlSession代理对象 36 SqlSession sqlSession = factory.openSession(); 37 // 通过代理对象调用接口中相应的方法 38 List<Emp> emps = sqlSession.selectList("com.panda.dao.EmpDao.getEmps"); 39 System.out.println(emps); 40 } 41 42 // 获取全体Emp对象 43 @Test 44 public void testGetEmps() throws Exception { 45 // 通过流获取主配置文件 46 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 47 // 获取SqlSession工厂对象 48 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 49 // 获取sqlSession对象 50 SqlSession sqlSession = factory.openSession(); 51 // 通过sqlSession对象获取代理对象 52 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 53 // 通过代理对象调用相应接口方法 54 try { 55 List<Emp> emps = mapper.getEmps(); 56 System.out.println(emps); 57 } catch (Exception e) { 58 e.printStackTrace(); 59 } finally { 60 sqlSession.close(); 61 is.close(); 62 } 63 } 64 65 // 通过Id获取单个Emp对象 66 @Test 67 public void testGetEmpById() throws Exception { 68 // 通过流获取主配置文件 69 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 70 // 获取SqlSession工厂对象 71 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 72 // 获取sqlSession对象 73 SqlSession sqlSession = factory.openSession(); 74 // 通过sqlSession对象获取代理对象 75 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 76 // 通过代理对象调用相应接口方法 77 try { 78 Emp empById = mapper.getEmpById(1); 79 System.out.println(empById); 80 } catch (Exception e) { 81 e.printStackTrace(); 82 } finally { 83 sqlSession.close(); 84 is.close(); 85 } 86 } 87 88 // 增加新员工 89 @Test 90 public void testInsertEmp() throws Exception { 91 // 通过流获取主配置文件 92 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 93 // 获取SqlSession工厂对象 94 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 95 // 获取sqlSession对象 96 SqlSession sqlSession = factory.openSession(); 97 // 通过sqlSession对象获取代理对象 98 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 99 // 创建emp对象 100 Emp emp = new Emp(); 101 emp.setName("test"); 102 emp.setGender("男"); 103 emp.setEmail("770233258@qq.com"); 104 // 通过代理对象调用相应接口方法 105 try { 106 mapper.insertEmp(emp); 107 sqlSession.commit(); 108 } catch (Exception e) { 109 e.printStackTrace(); 110 } finally { 111 sqlSession.close(); 112 is.close(); 113 } 114 // 返回插入行的id 115 System.out.println(emp.getId()); 116 } 117 118 // 修改员工信息 119 @Test 120 public void testUpdateEmp() throws Exception { 121 // 通过流获取主配置文件 122 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 123 // 获取SqlSession工厂对象 124 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 125 // 获取sqlSession对象 126 SqlSession sqlSession = factory.openSession(); 127 // 通过sqlSession对象获取代理对象 128 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 129 // 创建emp对象 130 Emp emp = new Emp(); 131 emp.setId(12); 132 emp.setName("panda"); 133 // 通过代理对象调用相应接口方法 134 try { 135 mapper.updateEmp(emp); 136 sqlSession.commit(); 137 } catch (Exception e) { 138 e.printStackTrace(); 139 } finally { 140 sqlSession.close(); 141 is.close(); 142 } 143 System.out.println(emp); 144 } 145 146 // 删除员工 147 @Test 148 public void testDeletEmpById() throws Exception { 149 // 通过流获取主配置文件 150 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 151 // 获取SqlSession工厂对象 152 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 153 // 获取sqlSession对象 154 SqlSession sqlSession = factory.openSession(); 155 // 通过sqlSession对象获取代理对象 156 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 157 // 通过代理对象调用相应接口方法 158 try { 159 mapper.deleteEmpById(12); 160 sqlSession.commit(); 161 } catch (Exception e) { 162 e.printStackTrace(); 163 } finally { 164 sqlSession.close(); 165 is.close(); 166 } 167 } 168 169 // 通过id和name获取单个Emp对象 170 @Test 171 public void testGetEmpByIdAndName() throws Exception { 172 // 通过流获取主配置文件 173 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 174 // 获取SqlSession工厂对象 175 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 176 // 获取sqlSession对象 177 SqlSession sqlSession = factory.openSession(); 178 // 通过sqlSession对象获取代理对象 179 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 180 // 通过代理对象调用相应接口方法 181 try { 182 Emp empByIdAndName = mapper.getEmpByIdAndName(1, "A"); 183 sqlSession.commit(); 184 System.out.println(empByIdAndName); 185 } catch (Exception e) { 186 e.printStackTrace(); 187 } finally { 188 sqlSession.close(); 189 is.close(); 190 } 191 } 192 193 // 通过id和name获取单个Emp对象使用命名参数 194 @Test 195 public void testGetEmpByIdAndNameByAtParam() throws Exception { 196 // 通过流获取主配置文件 197 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 198 // 获取SqlSession工厂对象 199 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 200 // 获取sqlSession对象 201 SqlSession sqlSession = factory.openSession(); 202 // 通过sqlSession对象获取代理对象 203 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 204 // 通过代理对象调用相应接口方法 205 try { 206 Emp empByIdAndNameByAtParam = mapper.getEmpByIdAndNameByAtParam(1, "A"); 207 sqlSession.commit(); 208 System.out.println(empByIdAndNameByAtParam); 209 } catch (Exception e) { 210 e.printStackTrace(); 211 } finally { 212 sqlSession.close(); 213 is.close(); 214 } 215 } 216 217 // Map方式通过id和name获取单个Emp对象 218 @Test 219 public void testGetEmpByIdAndNameByMap() throws Exception { 220 // 通过流获取主配置文件 221 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 222 // 获取SqlSession工厂对象 223 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 224 // 获取sqlSession对象 225 SqlSession sqlSession = factory.openSession(); 226 // 通过sqlSession对象获取代理对象 227 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 228 // 通过代理对象调用相应接口方法 229 try { 230 HashMap<String, Object> map = new HashMap<String, Object>(); 231 map.put("id", 1); 232 map.put("name", "A"); 233 Emp empByIdAndNameByMap = mapper.getEmpByIdAndNameByMap(map); 234 sqlSession.commit(); 235 System.out.println(empByIdAndNameByMap); 236 } catch (Exception e) { 237 e.printStackTrace(); 238 } finally { 239 sqlSession.close(); 240 is.close(); 241 } 242 } 243 244 // 通过id查询一条结果并封装成Map 245 @Test 246 public void testGetEmpByIdReturnMap() throws Exception { 247 // 通过流获取主配置文件 248 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 249 // 获取SqlSession工厂对象 250 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 251 // 获取sqlSession对象 252 SqlSession sqlSession = factory.openSession(); 253 // 通过sqlSession对象获取代理对象 254 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 255 // 通过代理对象调用相应接口方法 256 try { 257 Map<String, Object> empByIdReturnMap = mapper.getEmpByIdReturnMap(1); 258 System.out.println(empByIdReturnMap); 259 } catch (Exception e) { 260 e.printStackTrace(); 261 } finally { 262 sqlSession.close(); 263 is.close(); 264 } 265 } 266 267 // 通过id条件查询多条结果并封装成Map 268 @Test 269 public void testGetEmpsByIdReturnMap() throws Exception { 270 // 通过流获取主配置文件 271 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 272 // 获取SqlSession工厂对象 273 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 274 // 获取sqlSession对象 275 SqlSession sqlSession = factory.openSession(); 276 // 通过sqlSession对象获取代理对象 277 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 278 // 通过代理对象调用相应接口方法 279 try { 280 Map<Integer, Emp> empsByIdReturnMap = mapper.getEmpsByIdReturnMap(5); 281 System.out.println(empsByIdReturnMap); 282 } catch (Exception e) { 283 e.printStackTrace(); 284 } finally { 285 sqlSession.close(); 286 is.close(); 287 } 288 } 289 290 // 通过Id获取单个Emp对象级联dep对象使用resultMap 291 @Test 292 public void testGetEmpAndDepByIdUseResultMap() throws Exception { 293 // 通过流获取主配置文件 294 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 295 // 获取SqlSession工厂对象 296 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 297 // 获取sqlSession对象 298 SqlSession sqlSession = factory.openSession(); 299 // 通过sqlSession对象获取代理对象 300 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 301 // 通过代理对象调用相应接口方法 302 try { 303 Emp empAndDepByIdUseResultMap = mapper.getEmpAndDepByIdUseResultMap(1); 304 System.out.println(empAndDepByIdUseResultMap); 305 } catch (Exception e) { 306 e.printStackTrace(); 307 } finally { 308 sqlSession.close(); 309 is.close(); 310 } 311 } 312 313 // 通过Id获取单个Emp对象级联dep对象使用associate分步查询 314 @Test 315 public void testGetEmpAndDepByIdUseStep() throws Exception { 316 // 通过流获取主配置文件 317 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 318 // 获取SqlSession工厂对象 319 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 320 // 获取sqlSession对象 321 SqlSession sqlSession = factory.openSession(); 322 // 通过sqlSession对象获取代理对象 323 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 324 // 通过代理对象调用相应接口方法 325 try { 326 Emp empAndDepByIdUseStep = mapper.getEmpAndDepByIdUseStep(1); 327 // 开启延迟加载后查询empAndDepByIdUseStep则执行两条语句 328 // System.out.println(empAndDepByIdUseStep); 329 // 开启延迟加载后查询empAndDepByIdUseStep.getName()则只执行一条语句 330 System.out.println(empAndDepByIdUseStep.getName()); 331 } catch (Exception e) { 332 e.printStackTrace(); 333 } finally { 334 sqlSession.close(); 335 is.close(); 336 } 337 } 338 339 // 通过Id获取Dep对象及其下属子集Emp 340 @Test 341 public void testGetDepAndEmpsByIdUseCollection() throws Exception { 342 // 通过流获取主配置文件 343 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 344 // 获取SqlSession工厂对象 345 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 346 // 获取sqlSession对象 347 SqlSession sqlSession = factory.openSession(); 348 // 通过sqlSession对象获取代理对象 349 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 350 // 通过代理对象调用相应接口方法 351 try { 352 Dep depAndEmpsByIdUseCollection = mapper.getDepAndEmpsByIdUseCollection(4); 353 System.out.println(depAndEmpsByIdUseCollection); 354 System.out.println(depAndEmpsByIdUseCollection.getEmps()); 355 } catch (Exception e) { 356 e.printStackTrace(); 357 } finally { 358 sqlSession.close(); 359 is.close(); 360 } 361 } 362 363 // 通过Id获取单个Dep对象级联Emps对象集使用collection分步查询 364 @Test 365 public void testGetDepAndEmpsByIdUseStep() throws Exception { 366 // 通过流获取主配置文件 367 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 368 // 获取SqlSession工厂对象 369 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 370 // 获取sqlSession对象 371 SqlSession sqlSession = factory.openSession(); 372 // 通过sqlSession对象获取代理对象 373 EmpDao mapper = sqlSession.getMapper(EmpDao.class); 374 // 通过代理对象调用相应接口方法 375 try { 376 Dep depAndEmpsByIdUseStep = mapper.getDepAndEmpsByIdUseStep(4); 377 // 调用depAndEmpsByIdUseStep.getDep_name()验证只执行一条语句 378 System.out.println(depAndEmpsByIdUseStep.getDep_name()); 379 // 调用depAndEmpsByIdUseStep验证执行两条语句 380 System.out.println(depAndEmpsByIdUseStep); 381 } catch (Exception e) { 382 e.printStackTrace(); 383 } finally { 384 sqlSession.close(); 385 is.close(); 386 } 387 } 388 389 }
2.MybatisDynamicSqlTest.java(动态部分)
1 package com.panda.test; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 import org.apache.ibatis.io.Resources; 7 import org.apache.ibatis.session.SqlSession; 8 import org.apache.ibatis.session.SqlSessionFactory; 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 10 import org.junit.Test; 11 import com.panda.beans.Emp; 12 import com.panda.dao.EmpDynamicSqlDao; 13 14 /** 15 * @author Jpanda 16 */ 17 public class MybatisDynamicSqlTest { 18 // ifwhere多条件动态sql查询Emps集 19 @Test 20 public void testGetEmpsByConditionIfWhere() throws Exception { 21 // 通过流获取主配置文件 22 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 23 // 获取SqlSession工厂对象 24 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 25 // 获取sqlSession对象 26 SqlSession sqlSession = factory.openSession(); 27 // 通过sqlSession对象获取代理对象 28 EmpDynamicSqlDao mapper = sqlSession.getMapper(EmpDynamicSqlDao.class); 29 // 通过代理对象调用相应接口方法 30 try { 31 Emp condition = new Emp(); 32 condition.setId(1); 33 condition.setName("A"); 34 condition.setEmail("1@QQ.COM"); 35 condition.setGender("男"); 36 List<Emp> empsByConditionIfWhere = mapper.getEmpsByConditionIfWhere(condition); 37 System.out.println(empsByConditionIfWhere); 38 } catch (Exception e) { 39 e.printStackTrace(); 40 } finally { 41 sqlSession.close(); 42 is.close(); 43 } 44 } 45 46 // iftrim多条件动态sql查询Emps集 47 @Test 48 public void testGetEmpsByConditionIfTrim() throws Exception { 49 // 通过流获取主配置文件 50 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 51 // 获取SqlSession工厂对象 52 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 53 // 获取sqlSession对象 54 SqlSession sqlSession = factory.openSession(); 55 // 通过sqlSession对象获取代理对象 56 EmpDynamicSqlDao mapper = sqlSession.getMapper(EmpDynamicSqlDao.class); 57 // 通过代理对象调用相应接口方法 58 try { 59 Emp condition = new Emp(); 60 condition.setId(1); 61 condition.setName("A"); 62 condition.setEmail("1@QQ.COM"); 63 // condition.setGender("男"); 64 List<Emp> empsByConditionIfTrim = mapper.getEmpsByConditionIfTrim(condition); 65 System.out.println(empsByConditionIfTrim); 66 } catch (Exception e) { 67 e.printStackTrace(); 68 } finally { 69 sqlSession.close(); 70 is.close(); 71 } 72 } 73 74 // choose多条件逐一判断动态sql查询Emps值 75 @Test 76 public void testGetEmpsByConditionChoose() throws Exception { 77 // 通过流获取主配置文件 78 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 79 // 获取SqlSession工厂对象 80 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 81 // 获取sqlSession对象 82 SqlSession sqlSession = factory.openSession(); 83 // 通过sqlSession对象获取代理对象 84 EmpDynamicSqlDao mapper = sqlSession.getMapper(EmpDynamicSqlDao.class); 85 // 通过代理对象调用相应接口方法 86 try { 87 Emp condition = new Emp(); 88 condition.setId(1); 89 condition.setName("A"); 90 condition.setEmail("1@QQ.COM"); 91 condition.setGender("男"); 92 List<Emp> empsByConditionChoose = mapper.getEmpsByConditionChoose(condition); 93 System.out.println(empsByConditionChoose); 94 } catch (Exception e) { 95 e.printStackTrace(); 96 } finally { 97 sqlSession.close(); 98 is.close(); 99 } 100 } 101 102 // foreach查询Emps集 103 @Test 104 public void testGetEmpsByIdsForeach() throws Exception { 105 // 通过流获取主配置文件 106 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 107 // 获取SqlSession工厂对象 108 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 109 // 获取sqlSession对象 110 SqlSession sqlSession = factory.openSession(); 111 // 通过sqlSession对象获取代理对象 112 EmpDynamicSqlDao mapper = sqlSession.getMapper(EmpDynamicSqlDao.class); 113 // 通过代理对象调用相应接口方法 114 try { 115 List<Integer> ids = new ArrayList<Integer>(); 116 ids.add(1); 117 ids.add(2); 118 ids.add(3); 119 List<Emp> empsByIdsForeach = mapper.getEmpsByIdsForeach(ids); 120 System.out.println(empsByIdsForeach); 121 } catch (Exception e) { 122 e.printStackTrace(); 123 } finally { 124 sqlSession.close(); 125 is.close(); 126 } 127 } 128 129 // set多条件动态sql设置Emp值 130 @Test 131 public void testUpdateEmpByConditionIfSet() throws Exception { 132 // 通过流获取主配置文件 133 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 134 // 获取SqlSession工厂对象 135 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 136 // 获取sqlSession对象 137 SqlSession sqlSession = factory.openSession(); 138 // 通过sqlSession对象获取代理对象 139 EmpDynamicSqlDao mapper = sqlSession.getMapper(EmpDynamicSqlDao.class); 140 // 通过代理对象调用相应接口方法 141 try { 142 Emp condition = new Emp(); 143 condition.setId(13); 144 condition.setName("Jpanda"); 145 condition.setEmail("Jpanda@QQ.COM"); 146 // condition.setGender("男"); 147 mapper.updateEmpByConditionIfSet(condition); 148 sqlSession.commit(); 149 } catch (Exception e) { 150 e.printStackTrace(); 151 } finally { 152 sqlSession.close(); 153 is.close(); 154 } 155 } 156 157 // foreach批量添加Emps 158 @Test 159 public void testInsertLotEmps() throws Exception { 160 // 通过流获取主配置文件 161 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 162 // 获取SqlSession工厂对象 163 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); 164 // 获取sqlSession对象 165 SqlSession sqlSession = factory.openSession(); 166 // 通过sqlSession对象获取代理对象 167 EmpDynamicSqlDao mapper = sqlSession.getMapper(EmpDynamicSqlDao.class); 168 // 通过代理对象调用相应接口方法 169 try { 170 ArrayList<Emp> emps = new ArrayList<Emp>(); 171 emps.add(new Emp(null, "AA", "AA", "男", null)); 172 emps.add(new Emp(null, "BB", "BB", "男", null)); 173 emps.add(new Emp(null, "CC", "CC", "男", null)); 174 mapper.insertLotEmps(emps); 175 sqlSession.commit(); 176 } catch (Exception e) { 177 e.printStackTrace(); 178 } finally { 179 sqlSession.close(); 180 is.close(); 181 } 182 } 183 }
文章内容为本人自学尚硅谷Mybatis框架课程学习笔记,没有具体笔记,都融入到所有的代码和注释中了,我个人喜欢这样的笔记方式,内容命名方法和原始数据与原课程不相符,内容是在
自己的理解的基础上写的。新手上路,其中可能存在各种纰漏和bug,测试方法本人学习过程中都全部正确执行验证过了。本文目的仅为了自己以后回顾复习使用,快速复制自己的习惯搭建方式。
其中有很多代码可能在其它人看来无用或者多于,很多时候我是为了验证某个使用功能理解知识点人为构造的冗余过程,比如其中的有些resultMap映射,仅仅是为了验证该功能。课程中讲到的
知识点个人感觉全部都有包括进去。当然仅仅使用配置文件模式,没有使用注解配置。
原文链接:https://www.cnblogs.com/jpanda/p/11496893.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- MyBatis中的$和#,用不好,准备走人! 2020-06-11
- 学习Java 8 Stream Api (4) - Stream 终端操作之 collect 2020-06-11
- java学习之第一天 2020-06-11
- Java学习之第二天 2020-06-11
- SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash