一,在Mybatis实现CRUD的三种方式
在Mybatis有三种方式实现增删改查分别实现dao,代理dao,注解
一,直接实现dao
直接实现dao就是直接用实现类来调用方法,它也需要写映射文件
MySQL中的表结构:
① map映射文件:
<?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 namespace="com.wqls.imbwql"> <select id="wqlfq" resultType="com.wqls.bmswql"> select * from bm </select> </mapper>
② 新建实体类:
1,实体类必须和表结构对映,形成映射关系,
2,实现Serializable序列号接口
public class bmswql implements Serializable { int id; String bmname; public void setId(int id) { this.id = id; } public void setBmname(String bmname) { this.bmname = bmname; } public int getId() { return id; } public String getBmname() { return bmname; } @Override public String toString() { return "bm{" + "id=" + id + ", bmname='" + bmname + '\'' + '}'; } }
③ 新键接口类:需要什么操作就写什么方法,注意返回值类
public interface imbwql { public List<bmswql> bmsfq(); }
④ 写接口实现类(直接实现dao接口):
public class fqbm implements imbwql{ InputStream a = Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(a); List<bmswql> aw=null; public fqbm() throws IOException { } public List<bmswql> bmsfq() { //sqlid:映射文件中的namespace + 映射ID String sqlid="com.wqls.imbwql.wqlfq"; SqlSession sqlSession = sessionFactory.openSession(); aw=sqlSession.selectList(sqlid); return aw; } }
⑤ 测试:
public static void main(String[] args) throws IOException { fqbm a=new fqbm(); List<bmswql> s=a.bmsfq(); for(bmswql sd:s){ System.out.print(sd); } }
结果:
bm{id=1, bmname='市场部'} bm{id=2, bmname='人力资源部'} bm{id=3, bmname='安保部'} bm{id=4, bmname='开发部'}
二,代理dao
代理dao不需要写实现类,提供代理接口,调用代理方法(session.getMapper())帮你实现
① 映射文件:和直接实现dao一样
<?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.wqls.imbwql"> <!--id必须要和接口的方法名一致--> <select id="wqlfq" resultType="com.wqls.bmswql"> select * from bm </select> </mapper>
② 实体类:和直接实现dao一样,略
③接口:和直接实现dao一样,略
④ 测试(重点):
public static void main(String[] args) throws IOException { //读取主配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml"); //session工厂创建者(创建者模式:创建工厂) SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //调用build产生一个Session工厂 SqlSessionFactory factory = builder.build(inputStream); //Session工厂创建一个Sesscee SqlSession session = factory.openSession(); //调用接口代理方式,创建一个代理接口的实现类, Iuser iuser=session.getMapper(wqlfq.class); //调用代理接口的方法 List<bmswql> list = iuser.findall(); for (bmswql a:list){ System.out.println(a); } }
结果:
bm{id=1, bmname='市场部'} bm{id=2, bmname='人力资源部'} bm{id=3, bmname='安保部'} bm{id=4, bmname='开发部'}
三 ,注解实现
关键注解词 :
@Insert : 插入sql , 和xml insert sql语法完全一样
@Select : 查询sql, 和xml select sql语法完全一样
@Update : 更新sql, 和xml update sql语法完全一样
@Delete : 删除sql, 和xml delete sql语法完全一样
@Param : 入参
@Results : 结果集合
@Result : 结果
实现步骤:
注解实现不需要写映射文件,当要在主配置文件中配置mappers
①不要map映射文件
②实体类一致
③主配置文件:其他不变,只要配置mappers
<mappers> <!--设置要使用注解的接口,在方法上添加方法--> <mapper class="com.wqls.imbwql"/> </mappers>
④ 接口:
public interface imbwql { @Select("select * from bm") public List<bmswql> select(); }
⑤测试(也需要代理接口):
public static void main(String[] args) throws IOException { InputStream stream = Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(stream); SqlSession session = sqlSessionFactory.openSession(true); imbwql iprople1 = session.getMapper(imbwql.class); List<bmswql> ad = iprople1.select(); for(bmswql s : ad){ System.out.println(s); } }
四,Mybatis的执行流程
Mybatis的执行流程其实就是Session的产生和销毁
①读取主配置文件:Mybatis主要用don4f来进行xml解析
②创建工厂建造者:用到创建者模式,一般工厂的创建都要到这种模式(可以多工厂创建)
③创建工厂:工厂模式,来创建对象
④创建Sqlsession对象:通过Sqlsession可以进行代理操作,和解析读取映射xml文件
⑤创建代理接口对象:Seesion通过Mapper方法构建代理接口实现类
⑥读取解析映射xml文件:对xml解析,反射到实体类上,对象实体类进行映射
⑦通过接口进行一系列的操作
⑧销毁Sqlsession
其实通过这个流程我们可以自定义一个类似于mybatis的功能,之后单独写一遍
二,Mybatis的增删改查(以代理dao方式实现)
Mybatis增删改查其实挺简单,流程和之前的是一致的,只是返回值有不同
一,查(略……)
二,增加
表结构:
① 映射文件
<mapper namespace="com.wql.Iuser"> <insert id="insert" parameterType="com.wql.user"> insert into fq values (${id},'${name}',${random}) </insert> </mapper>
② 实体类
public class user implements Serializable { int id; String name; int random; public user(){ } public user(int id, String name, int random) { this.id = id; this.name = name; this.random = random; } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setRandom(int random) { this.random = random; } @Override public String toString() { return "user{" + "id=" + id + ", name='" + name + '\'' + ", random=" + random + '}'; } }
③ 接口
ublic interface Iuser {
//增加数据(插入数据传入对象) public Boolean insert(user wql);}
④测试
public static void main(String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream); SqlSession session = factory.openSession(); Iuser iuser=session.getMapper(Iuser.class);
Boolean a=iuser.insert(new user(18,"SB",101)); System.out.print(a); session.commit();
结果:
true
三,修改
①实体类(与增加一样,略……)
②映射文件
<mapper namespace="com.wql.Iuser"> <update id="update"> update fq set name=#{name} where id=#{id} </update> </mapper>
③ 接口
ublic interface Iuser { //修改数据(修改数据传入对象) public void update(user u);}
④测试
public static void main(String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream); SqlSession session = factory.openSession(); Iuser iuser=session.getMapper(Iuser.class); iuser.update(new user(18,"LUOQIN",10)); session.commit();
}}
四,删除
①实体类(一样,略……)
②映射文件
<mapper namespace="com.wql.Iuser"> <!--传入判断字段名的值--> <delete id="delete" parameterType="Int" > delete from fq where id=#{a} </delete> </mapper>
③接口
ublic interface Iuser { //删除数据(修改数据传入id字段的int值) public void delect(int u);}
④测试
public static void main(String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream); SqlSession session = factory.openSession(); Iuser iuser=session.getMapper(Iuser.class); iuser.delete(14); session.commit();}}
五,CRUD的细节问题
查询时:只能用javaBean对象进行映射接收所有result所有一般是JavaBean,但也可以有map集合接收单个数据或者多个数据
增加,修改,删除:输入类型也只能是javaBean,返回值一般都用void(无返回),假如是int的话(成功为1,不成功为o),为Boolean时(你懂的)
六,select的三种返回方式
一,javaBean返回(前后都是这种方式,略……)
二,Map集合接收单条数据
map接收单条数据,表和map集合产生映射,字段会成为键,字段值会变成value,通过键获取value
表结构:
① 映射文件
<?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.fq.iprople"> <!--单条数据映射进Map集合--> <select id="select3" resultType="Map"> select * from prople where id=#{a} </select> </mapper>
② 实体类
public class prople { int id; String name; int bmid; int age; String xb; public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setBmid(int bmid) { this.bmid = bmid; } public void setAge(int age) { this.age = age; } public void setXb(String xb) { this.xb = xb; } public int getId() { return id; } public String getName() { return name; } public int getBmid() { return bmid; } public int getAge() { return age; } public String getXb() { return xb; } @Override public String toString() { return "prople{" + "id=" + id + ", name='" + name + '\'' + ", bmid=" + bmid + ", age=" + age + ", xb='" + xb + '\'' + '}'; } }
③接口
public interface iprople { //单条数据查询(保存到Map集合) public Map<String,String> select3(int id); }
④测试:
InputStream stream= Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder sessionFactoryBuilder= new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory=sessionFactoryBuilder.build(stream); SqlSession session=sqlSessionFactory.openSession(true); iprople iprople1= session.getMapper(iprople.class); Map<String, String> map=iprople1.select3(1); Set set= map.keySet(); for(Object a:set){ System.out.println(a); } }
结果:
name bmid xb id age
三,map集合接收多条数据
Map接收多条数据,需要在接口方法上加@MapKey(value = "表字段名"),表明以那个字段为键,value就是JavaBean对象
① 实体类(和上面一样,略……)
②map映射文件
<?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.fq.iprople"> <!--多条数据映射进Map集合--> <select id="select4" resultType="prople"> select * from prople; </select> </mapper>
③ 接口
public interface iprople { //4,多条数据查询(保存到Map集合) @MapKey(value = "id")//表明以表ID为键 public Map<Integer,prople> select4(); }}
④ 测试
public static void main(String[] args) throws IOException { InputStream stream= Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder sessionFactoryBuilder= new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory=sessionFactoryBuilder.build(stream); SqlSession session=sqlSessionFactory.openSession(true); iprople iprople1= session.getMapper(iprople.class); Map<Integer, prople> map=iprople1.select4(); Set set= map.keySet(); for(Object a:set){ System.out.println(map.get(a)); } }
结果:
prople{id=1, name='WQL', bmid=1, age=23, xb='男'} prople{id=2, name='张三', bmid=2, age=33, xb='男'} prople{id=3, name='李四', bmid=4, age=21, xb='男'} prople{id=4, name='FQ', bmid=2, age=20, xb='女'}
三,Mybatis参数传值方式
主要讲Mybatis参数传值的两种方式
一,参数传值的两种方式${}和#{}
$底层引用的是JDBC的Statement而#底层引用的是JDBC的PreparedStatement,他们自带PreparedStatement和Statement的属性
#:
$:
1、#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:where username=#{username},如果传入的值是111,那么解析成sql时的值为where username="111", 如果传入的值是id,则解析成的sql为where username="id".
2、$将传入的数据直接显示生成在sql中。
如:where username=${username},如果传入的值是111,那么解析成sql时的值为where username=111;
3、针对上面的sql,如果传入的值是;drop table user;,
那么第一条用#{}的sql解析为:select id, username, password, role from user where username=";drop table user;"
那么第二条用${}的sql解析为:select id, username, password, role from user where username=;drop table user;
这时候已经sql注入了。
3、#方式能够很大程度防止sql注入,$方式无法防止Sql注入。
4、$方式一般用于传入数据库对象,例如传入表名和列名,还有排序时使用order by动态参数时需要使用$ ,ORDER BY ${columnName}
5、一般能用#的就别用$,若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。
6、在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。
二,传入的参数数量和类型
一,JavaBean作为参数传入
当传入的参数是javaBean对象时:
1,${}:通过${对象属性名获取},但要注意引号问题
2,#{}:和${}一样通过对象属性获取值
不举例
二,单个其他基本类型和包装类参数传值
在Mybatis中非javaBean对象类型的其他数据类下,单个参数传值,会把它封装成一个map集合,有两个键:value,_parameter
例:有一段代码
接口:
public interface fq123 { public wql123 select(Integer a); }
实体类:
public class wql123 implements Serializable { Integer id; String bmname; public void setId(int id) { this.id = id; } public void setBmname(String bmname) { this.bmname = bmname; } public int getId() { return id; } public String getBmname() { return bmname; } @Override public String toString() { return "bm{" + "id=" + id + ", bmname='" + bmname + '\'' + '}'; }
map映射文件:我们需要填写的部分
<mapper namespace="com.testsw.fq123"> <select id="select" resultType="com.testsw.wql123"> select * from bm where id = #{需要填写的部分} </select> </mapper>
#{}和${}对参数的接收:
1,#{}的方式:
① 可以按字段来获取
#{id}
② 可以有任意变量获取
#{随便写}
③用value键来获取参数值
#{value}
④用_parameter键来获取值
#{_parameter}
2,${}的方式:它的方式比#要少,它不能通过字段名和任意去获,只能通过Map的键获取值
① 用value获取参数值
${value}
②用_parameter获取参数值
${_parameter}
三,多个其他基本类型和包装类参数传值
多个和单个其实是一样的,Mybatis也会把多个参数封装进map集合中,只是键有所不同,它根据参数的顺序分为两种
1,arg0,arg1,arg2……
2,param1,param2,……
四,有map集合作为参数传值
之前mybatis间接把参数转化成map集合,我们也可以直接传入map集合,自定义键来取值
例:实体类和接口上面那个案例有
① 映射文件:
<?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"> <!--_parameter--> <mapper namespace="com.testsw.fq123"> <select id="select" resultType="com.testsw.wql123"> select * from bm where id = #{wql} </select> </mapper>
② 测试:
public static void main(String[] args) throws IOException { InputStream stream = Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(stream); SqlSession session = sqlSessionFactory.openSession(true); fq123 iprople1 = session.getMapper(fq123.class); Map map = new HashMap(); map.put("wql",1); wql123 a=iprople1.select(map); System.out.println(a); }
结果:
bm{id=1, bmname='市场部'}
五,通过@param注解来自定义键
mybatis提供了一个@param注解,来实现自定义键
语法:@param("自定义键名称")
案例:实体类是一样的
接口:
public interface fq123 { public wql123 select(@Param("WQL") int a); }
map映射文件:
<?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"> <!--_parameter--> <mapper namespace="com.testsw.fq123"> <select id="select" resultType="com.testsw.wql123"> select * from bm where id = ${WQL} </select> </mapper>
测试:
public static void main(String[] args) throws IOException { InputStream stream = Resources.getResourceAsStream("mybatisconfig.xml"); SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(stream); SqlSession session = sqlSessionFactory.openSession(true); fq123 iprople1 = session.getMapper(fq123.class); wql123 a=iprople1.select(1); System.out.println(a); }
结果:
bm{id=1, bmname='市场部'}
四,多表关联关系
多表查询依赖多表关联关系,mybatis多表联查和MySQL的设置主外键的方式类似,它提供自定义映射关系来建立表连接,
多表关联的几种方式:
1,result标签之间设定
2,association设定
3,分步查询
一,resultMap自定义映射
和MySQL多表联查依赖主外键一样,Mybatis多表查询依赖自定义映射,
resultMap的属性:
1,id:映射的标识,自定义
2,type:映射的实体类类型,写全限定类名就行
子标签:
id:设置主键和对象属性的映射
result:设置其他字段和对象属性映射
association:设置映射,也可以设置分步操作
子标签的公共属性:
property:对象的属性名
column:表的字段名
二,使用标准的result做多表查询
两个表的表结构:
实体类:
部门表对映的实体类:
import java.io.Serializable; public class bmswql implements Serializable { int id; String bmname; //set和get方法不显示 @Override public String toString() { return "bm{" + "id=" + id + ", bmname='" + bmname + '\'' + '}'; } }
员工表对映的实体类:
public class wqluser { int id; String name; int age; String xb; int bmid; //需要关联的表的实体类对象,只是映射的关键 bm bms; //Set和get方法这里不显示了 @Override public String toString() { return "wqluser{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", xb='" + xb + '\'' + ", bmname=" + bms + ", bmid=" + bmid + '}'; } }
接口:
public interface Iwqluser { public List<wqluser> select1();}
映射文件:
<mapper namespace="com.duobiao.Iwqluser"> <resultMap id="wql" type="com.duobiao.wqluser"> <id property="id" column="id"/> <result column="name" property="name"/> <result column="age" property="age"/> <result column="xb" property="xb"/> <result column="bmid" property="bmid"/> <!--其他表的映射--> <result column="id" property="bms.id"/> <result column="bmname" property="bms.bmname"/> </resultMap> <select id="select1" resultMap="wql"> select prople.id,bm.bmname,prople.name,prople.age,prople.xb,prople.bmid from prople left join bm on prople.bmid=bm.id </select> </mapper>
二,使用标准的association做多表查询
association的属性:
property:要连接的对象名
javaType:连接对象的java类型,直接写全限定类名
select:要分步的map的id,填其他查询的id
子标签:result功能和上面的一样
其他不变,只是对映射文件就行修改
映射文件:
<mapper namespace="com.duobiao.Iwqluser"> <resultMap id="wql" type="com.duobiao.wqluser"> <id property="id" column="id"/> <result column="name" property="name"/> <result column="age" property="age"/> <result column="xb" property="xb"/> <result column="bmid" property="bmid"/> <!----> <association property="bms" javaType="com.duobiao.bm"> <result column="bmname" property="bmname"/> <result column="id" property="id"/> </association> </resultMap>
<select id="select1" resultMap="wql"> select prople.id,bm.bmname,prople.name,prople.age,prople.xb,prople.bmid from prople left join bm on prople.bmid=bm.id </select> </Mapper>
三,分步查询
一个查询连接下一个查询,这个操作和下一个操作共同进行
<mapper namespace="com.duobiao.Iwqluser"> <resultMap id="wqlusers" type="com.duobiao.wqluser"> <id property="id" column="id"/> <result column="name" property="name"/> <result column="age" property="age"/> <result column="xb" property="xb"/> <result column="bmid" property="bmid"/> <!--property:要连接的对象名(就是员工类里面的bm对象) select:下一步要执行的resultMap column:以什么属性作为传入参数 --> <association property="bms" select="select3" column="bmid"/> </resultMap> <resultMap id="bms" type="com.duobiao.bm"> <result column="id" property="id"/> <result column="bmname" property="bmname"/> </resultMap> <select id="select2" resultMap="wqlusers"> select id,name,age,xb,bmid from prople where id=#{a} </select> <select id="select3" resultMap="bms"> select * from bm where id=#{b} </select> </mapper>
五,动态SQL
动态SQL是Mybatis的一个特征
if 标签
if 标签通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。
<if test="name != null and name != ''"> and NAME = #{name} </if>
foreach 标签
foreach 标签主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中
<!-- in查询所有,不分页 --> <select id="selectIn" resultMap="BaseResultMap"> select name,hobby from student where id in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
属性介绍:
- collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。
- item :表示在迭代过程中每一个元素的别名
- index :表示在迭代过程中每次迭代到的位置(下标)
- open :前缀
- close :后缀
- separator :分隔符,表示迭代时每个元素之间以什么分隔
choose 标签
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when
的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。
if 是与(and)的关系,而 choose 是或(or)的关系。
<select id="getStudentListChoose" parameterType="Student" resultMap="BaseResultMap"> SELECT * from STUDENT WHERE 1=1 <where> <choose> <when test="Name!=null and student!='' "> AND name LIKE CONCAT(CONCAT('%', #{student}),'%') </when> <when test="hobby!= null and hobby!= '' "> AND hobby = #{hobby} </when> <otherwise> AND AGE = 15 </otherwise> </choose> </where> </select>
Comments | 1 条评论
博主 匿名
量变的质变
Warning: Undefined variable $return_smiles in /www/wwwroot/wql_luoqin_ltd/wp-content/themes/Sakura/functions.php on line 1109