python做网站挣钱,开一个免费网站,自己做网站需要主机吗,建设银行贷款业务网站目录
一、MyBatis 简介
1、MyBatis 简介
2、工作流程
二、入门案例
1、准备工作
2、示例
三、Mapper 代理开发
1、问题简介
2、工作流程
3、注意事项
4、测试
四、核心配置文件 mybatis-config.xml
1、environment
2、typeAilases
五、基于 xml 的查询操作
1、…目录
一、MyBatis 简介
1、MyBatis 简介
2、工作流程
二、入门案例
1、准备工作
2、示例
三、Mapper 代理开发
1、问题简介
2、工作流程
3、注意事项
4、测试
四、核心配置文件 mybatis-config.xml
1、environment
2、typeAilases
五、基于 xml 的查询操作
1、准备环境
2、 映射列名
3、根据 id 查询 #{ id }
4、参数传递的 6 种方式
6、动态查询
六、基于 xml 的添加操作
1、添加数据
2、事务提交
3、主键返回
七、基于 xml 的修改操作
1、修改全部字段
2、修改动态字段
八、基于 xml 的删除操作
1、根据 id 删除
2、批量删除
九、注解开发
1、简单的增删改查 一、MyBatis 简介
1、MyBatis 简介
MyBatis 是一款优秀的持久层框架它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJOPlain Old Java Objects普通老式 Java 对象为数据库中的记录。
2、工作流程
1每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的
SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例即 xml 方式、注解方式
2SqlSessionFactory 顾名思义我们可以从中获得 SqlSession 的实例
SqlSession 提供了在数据库执行 SQL 命令所需的所有方法如selectList、selectOne通过 SqlSession 实例来执行已映射的 SQL 语句根据对应 namespace id 执行自定义的 SQL 语句
3释放资源
SqlSession.close()
整个流程大致为 二、入门案例
显然重点在于 MyBatis 的配置文件以及执行相应方法所需要的 mapper 映射文件。下面通过 1 个示例来说明。
1、准备工作
1引入相关依赖
这里使用的数据库是 PostgreSQL可以根据自己的数据库更改。
dependenciesdependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.10/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependencydependencygroupIdorg.postgresql/groupIdartifactIdpostgresql/artifactIdversion42.6.0/version/dependency
/dependencies
2创建一个 Pojo 实体类
构造函数、toString 等等方法自行添加。
package com.demo.pojo;public class User {private Integer id;private String username;private String password;private Integer gender;private String address;
}3创建对应的 user 表格 2、示例
我们按照前面的大致流程完成示例。
1mybatis-config.xml
文件命名任意在 resource 目录下创建/mybatis-config.xml首先需要配置数据库信息其次需要链接 mapper 映射文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfiguration!--设置连接数据库的环境--environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver valueorg.postgresql.Driver/property nameurl valuejdbc:postgresql://localhost:5432/MyDatabase/property nameusername valuepostgres/property namepassword value123456//dataSource/environment/environments!--引入sql映射文件--mappers!-- 单独引入一个 mapper --mapper resourcemapper/UserMapper.xml//mappers
/configuration2UserMapper.xml
在 resource 目录下创建/mapper/mybatis-config.xmlnamespace命名空间一般可以随便写示例一和示例二有所不同id作为当前编写语句的标识符通常与 namespace 连用resultType顾名思义返回类型
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespaceMyUserselect idselectAll resultTypecom.demo.pojo.Userselect * from MyUser; !-- PostgreSQL 写法 --/select
/mapper
3Java 代码
Test
public void test1() throws IOException {// 1.加载核心配置文件获取 sqlSessionFactory 对象String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);// 2.获取 sqlSession 对象用来执行sql语句SqlSession sqlSession sqlSessionFactory.openSession();// 3.执行 sqlListUser userList sqlSession.selectList(MyUser.selectAll);System.out.println(userList);// 4.释放资源sqlSession.close();
}
三、Mapper 代理开发
1、问题简介
我们会发现上面的示例有一个大问题当我们使用 sqlSession 对象调用指定的 SQL 语句时传入了一个字符串常量 MyUser.selectAll。 这种硬编码的问题显然不利于后期的维护并且在编写的时候也需要来回查找对应的 SQL 语句的 id。
而我们的 Mapper 代理开发的目的
解决原生方式中的硬编码问题简化后期执行的 SQL
2、工作流程
处理哪个 Pojo 实体类我们就可以创建对应的 mapper 代理对象mapper 代理对象就是一个接口 使用 sqlSession 获取指定的 mapper 代理对象通过 class然后使用 mapper 执行目标 SQL 语句的方法 目标方法的方法名与我们在 xml 文件中设置的 id 值一致 3、注意事项
使用 mapper 代理对象需要 mapper 接口和相同文件名的 xml 在同一个目录下因此在 resources 目录下创建软件包若 resource 没有软件包选项则用 com/demo/mapper 来创建目录或者将 resources 标记为源代码根目录 mapper 配置文件的 namespace 需要改成 mapper 代理对象的类路径 由于以后很肯能会有大量的 Pojo 实体类需要用到 Mapper因此可以在 mybatis-config.xml 中使用包扫描 4、测试
1Java 代码
Test
public void test2() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();// mapper 代理对象需要 mapper 接口 和 xml 在同一个目录下因此在 resources 目录下创建软件包// 没有软件包选项则用 com/demo/mapper 来创建目录或者将 resources 标记为源代码目录UserMapper userMapper sqlSession.getMapper(UserMapper.class);ListUser userList userMapper.selectAll();System.out.println(userList);sqlSession.close();
}
2Mapper 接口类
package com.demo.mapper;import com.demo.pojo.User;import java.util.List;public interface UserMapper {ListUser selectAll();
}
3mybatis-config.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfiguration!--设置连接数据库的环境--environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver valueorg.postgresql.Driver/property nameurl valuejdbc:postgresql://localhost:5432/MyDatabase/property nameusername valuepostgres/property namepassword value123456//dataSource/environment/environments!--引入sql映射文件--mappersmapper resourcecom/demo/mapper/UserMapper.xml//mappers
/configuration4UserMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.demo.mapper.UserMapperselect idselectAll resultTypecom.demo.pojo.Userselect * from MyUser;/select
/mapper
四、核心配置文件 mybatis-config.xml
详情可以参考https://mybatis.org/mybatis-3/zh/configuration.html
下面举两个例子。
1、environment
environment 用来配置数据源因此可以在 environments 中配置多个数据源。通过 default 属性值可以动态地切换数据源。
1transactionManager
事务管理方式。这个默认写 JDBC 即可后期开发使用的是 Spring 的事务管理方式。
2dataSource
数据源信息。后期开发也是使用 Spring 来配置数据源默认写上 POOLED 即可。
2、typeAilases
我们在 UserMapper.xml 中需要为返回类型写上类的全路径有一点麻烦。
使用 typeAilases 可以为 POJO 类配置一个别名设置好包的路径后它们的别名默认就是不区分大小写的类名。 五、基于 xml 的查询操作
1、准备环境
1创建表 brand 2创建实体类 Brand
package com.demo.pojo;public class Brand {private Integer id;private String brandName;private String companyName;private Integer order;private String description;private Integer status;
}3安装 MyBatisX 插件 当我们在 mapper 接口中写上相应的 SQL 语句的方法名时如果已经有很多方法了那么对比起来就很麻烦使用 MyBatisX 可以帮助我们快速定位。 蓝色头顶代表 mapper 的接口红色头顶代表 SQL 的映射文件点击红鸟或者蓝鸟可以在 mapper 接口和 SQL 映射文件之间进行切换
并且 MyBatisX 还能自动生成方法所对应的 SQL 的 id 2、resultMap 映射列名
有的人习惯在创建数据库表的时候列名使用 _ 下划线这样就会导致 MyBatis 无法将数据注入到 POJO 实例中。
而如果给每个带有 _ 下划线的列名都取别名写起来又非常麻烦所以 MyBatis 提供了一个 resultMap 标签用来将表的列名与 POJO 实体类的属性名做一一对应
resultMap idbrandResultMap typecom.demo.pojo.Brandresult columnbrand_name propertybrandName/result columncompany_name propertycompanyName/
/resultMapselect idselectAll resultMapbrandResultMapselect * from MyBrand;
/select 需要注意的是select 中不是写 resultType而是写 resultMap。 3、根据 id 查询 #{ id }
显然根据 id 查询时我们需要传入一个 Integer 类型的参数
接口添加参数 映射文件添加 #{id} MyBatis 会根据参数名与 #{ } 内的名做比较来进行注入。
select 有一个属性是 parameterType用于表示参数类型但一般都不写。
1${} 与 #{}
除了 #{ } 这种写法还可以用 ${ } 这种写法它们的区别在于
#{ }会先将 #{ } 替换成 ?然后再将传入的参数赋值给 ?${ }直接将传入的参数替换掉 ${ } 一般情况下我们都推荐使用 #{ }因为 #{ } 将 #{ } 替换成 ?是为了防止 SQL 注入而 ${ } 就不能防止 SQL 注入。 2特殊字符
假如我们写出如下 SQL 语句 显然 会被识别为一个标签的开始所以我们可以做如下措施
转义字符 CDATA 区 4、参数传递的 6 种方式
当我们希望接收如下两个参数来做查询。 1Param(value) Param 的 value 属性用来将其标注的参数按照 value 的属性值找到相同的 #{ value } 来进行注入。比如 value brandName就可以注入到 #{ brandName} 中。
2POJO 实体类 如果传递的参数都属于同一个 POJO 实体类那么就可以用一个实体类的参数来接收他们。这就要求 #{ } 占位符内的名称跟 POJO 实体类的属性名一致。
3Map Map 的要求就很明显了要求 key 的值与 #{ } 内的名称一致。
4Collection
封装为 Map 集合通过 #{ arg0 } 或 #{ collection } 获取可以使用 Param 注解替换 Map 中默认的 arg 键名。
5List
封装为 Map 集合通过 #{ arg0 } 或 #{ collection } 或 #{ list } 获取可以使用 Param 注解替换 Map 中默认的 arg 键名。
6Array
封装为 Map 集合通过 #{ arg0 } 或 #{ array } 获取可以使用 Param 注解替换 Map 中默认的 arg 键名。
7Java 测试代码
Test
public void testSelectByCondition() throws IOException {// 模拟从 web 接收参数Integer status 0;String companyName 华为;// 处理参数模糊查询companyName % companyName %;// 封装 Brand 对象Brand brand new Brand();brand.setStatus(status);brand.setCompanyName(companyName);// 设置 map 对象MapString, Object map new HashMap();map.put(status, status);map.put(companyName, companyName);String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);ListBrand brandList1 brandMapper.selectByConditions1(status, companyName);ListBrand brandList2 brandMapper.selectByConditions2(brand);ListBrand brandList3 brandMapper.selectByConditions3(map);System.out.println(第一种 brandList1);System.out.println(第二种 brandList2);System.out.println(第三种 brandList3);sqlSession.close();
}
5Mapper 配置文件
select idselectByConditions1 resultTypecom.demo.pojo.Brandselect * from MyBrand wherestatus #{ status } andcompanyName like #{ companyName } !-- PostgreSQL 需要 “” 保证大写 --
/select
select idselectByConditions2 resultTypecom.demo.pojo.Brandselect * from MyBrand wherestatus #{ status } andcompanyName like #{ companyName }
/select
select idselectByConditions3 resultTypecom.demo.pojo.Brandselect * from MyBrand wherestatus #{ status } andcompanyName like #{ companyName }
/select
6输出结果 6、动态查询
上面的例子其实有 Bug因为用户在操作的时候有可能只希望用一个 companyName 来查询目标数据。也就是说我们需要对原有 SQL 语句做动态修改没有传递过来的参数就不用。
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架你应该能理解根据不同条件拼接 SQL 语句有多痛苦例如拼接时要确保不能忘记添加必要的空格还要注意去掉列表最后一个列名的逗号。利用动态 SQL可以彻底摆脱这种痛苦。
下面通过几个标签完成动态查询
ifchoose and when
1if test 的多条件动态查询 test 属性值就是我们要做的逻辑判断。
使用 if 时由于 and 关键字不好控制所以一般都加上一个恒等式1 1。
select idselectByDynamic resultTypecom.demo.pojo.Brandselect *from MyBrandwhere 1 1if teststatus ! nulland status #{ status }/ifif testcompanyName ! null and companyName ! and companyName like #{ companyName }/if
/select
或者使用 where 标签会根据判断结果来连接也就是 and对应的语句。
select idselectByDynamic resultTypecom.demo.pojo.Brandselect *from MyBrandwhereif teststatus ! nullstatus #{ status }/ifif testcompanyName ! null and companyName ! companyName like #{ companyName }/if/where
/select
2choose 的单条件动态查询
有些情况下只允许根据一个的条件进行查询但是条件可以更改。
如果用户只输入一个参数所以可以不用 where。otherwise 可以用来防止用户一个都不输入。如果用户真的一个都不输入可以用 where这样可以省略 otherwise。
select idselectByDynamic resultTypecom.demo.pojo.Brandselect *from MyBrandwhere !-- 因为保证了用户只会输入一个参数所以可以不用 where --choosewhen teststatus ! nullstatus #{ status }/whenwhen testcompanyName ! null and companyName ! companyName like #{ companyName }/whenotherwise1 1/otherwise/choose
/select
六、基于 xml 的添加操作
1、添加数据
1接口 2Mapper 映射
insert idaddBrandinsert into MyBrand(brandName, companyName, order, description, status)values(#{brandName}, #{companyName}, #{order}, #{description}, #{status});
/insert
3Java 测试代码
Test
public void testAddBrand() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);Brand brand new Brand(null, iphone, Apple, 99, iphone 8, 1);brandMapper.addBrand(brand);ListBrand brandList brandMapper.selectAll();System.out.println(brandList);// 提交事务sqlSession.commit();sqlSession.close();
}
2、事务提交
在刚才添加数据的例子中我们发现多写了一句 sqlSession.commit()用于将 SQL 语句的操作提交。如果不写就会发现我们插入的数据没有添加到数据库。
1事务提交的设置方法
sqlSession.commit()手动提交事务sqlSessionFactory.openSession(true)在获取 sqlSession 的时候可以设置是否自动提交默认false即开启事务
3、主键返回
有时在数据添加成功后需要获取插入数据库的主键的值比如 id。
因为数据刚刚添加完成我们并不知道它的 id 值但是此时我们马上要用到 id 作为另一个表的外键那么就需要返回主键值。
1解决方法
在相应的 insert 标签中添加 useGeneratedKeys 和 KeyProperty 属性即可
useGeneratedKeys设置为 trueKeyProperty设置为需要返回的列
2示例
插入一个新的 brand然后获取其 id再次做查询验证 id。
2-1Mapper 映射
insert idaddBrandBackId useGeneratedKeystrue keyPropertyidinsert into MyBrand(brandName, companyName, order, description, status)values(#{brandName}, #{companyName}, #{order}, #{description}, #{status});
/insert
2-2Java 测试代码
Test
public void testAddBrand() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);Brand brand new Brand(null, iphone, Apple, 99, iphone 8, 1);brandMapper.addBrandBackId(brand);Integer id brand.getId();System.out.println(id);Brand tmp brandMapper.selectById(id);System.out.println(tmp);// 提交事务sqlSession.commit();sqlSession.close();
}
3输出结果 七、基于 xml 的修改操作
1、修改全部字段
传入一个 POJO 实体类做对应的 update 操作即可。
1接口 2Mapper 映射
update idupdateupdate MyBrandsetbrandName #{ brandName },companyName #{ companyName },order #{ order},description #{ description },status #{ status }where id #{ id };
/update
3Java 测试代码
Test
public void testUpdate() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);int count brandMapper.update(new Brand(9, Iphone, Apple, 66, iphone 18, 1));System.out.println(count);sqlSession.commit();sqlSession.close();}
2、修改动态字段
比如 User 对象密码的修改和其他的内容的修改一般是不会放在一起的修改密码时只需要修改 password其他内容不用修改。
使用 set 标签就可以实现动态 当 update 语句中没有使用 if 标签时如果有一个参数为 null都会导致错误。当在 update 语句中使用 if 标签时如果前面的 if 没有执行则会导致逗号多余错误。使用 set 标签将动态的配置 SET 关键字并剔除追加到条件末尾的任何不相关的逗号。使用 ifset 标签修改后如果某项为 null 则不进行更新而是保持数据库原值。 update idupdateupdate MyBrandsetif testbrandName ! nullbrandName #{ brandName },/ifif testcompanyName ! nullcompanyName #{ companyName },/ifif testorder ! nullorder #{ order },/ifif testdescription ! nulldescription #{ description },/ifif teststatus ! nullstatus #{ status },/if/setwhere id #{ id };
/update 八、基于 xml 的删除操作 1、根据 id 删除 1Mapper 映射文件 delete iddeleteByIddelete from MyBrand where id #{ id };
/delete 2Java 测试代码 Test
public void testDeleteById() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);int count brandMapper.deleteById(9);sqlSession.commit();sqlSession.close();} 2、批量删除 批量多选删除是我们经常遇到的需求。
实现方法就是将多个 id 封装成 id 数组SQL 语句中用 占位符来接收所有的 id 值。
但是现在问题就在于我们不能确定有多少个 id也就是不能确定有多少个 占位符。
1foreach
为了解决 in 语句的问题MyBatis 提供了一个 foreach 标签可以对一个集合进行遍历
collection表示传入的集合item遍历的每一个元素seperator元素之间的分隔符open/close指定开闭匹配的字符串
其中 collection 需要特别注意MyBatis 会将集合对象封装到一个 Map 对象通过 key 来获取我们传入的集合。
key 的值数组则写 arrayList 实例则写 list也可以用 Param 起别名。
2示例
2-1Mapper 映射文件
delete iddeleteByIdsdelete from MyBrand where id inforeach collectionarray itemid separator, open( close)#{ id }/foreach
/delete
九、注解开发
MyBatis 中并不一定使用完全注解开发通常
注解完成简单功能配置文件完成复杂功能
1、简单的增删改查
1Mapper 映射接口
Select(select * from \MyBrand\)
ListBrand selectAll();Insert(insert into \MyBrand\(\brandName\, \companyName\, \order\, description, status)\n values(#{brandName}, #{companyName}, #{order}, #{description}, #{status});)
void addBrand(Brand brand);Update(update \MyBrand\ set status #{ status })
int update(Brand brand);Delete(delete from \MyBrand\ where id #{ id };)
int deleteById(Integer id);
2Java 测试代码
Test
public void testAnnotation() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);// 增brandMapper.addBrand(new Brand(null, iphone, Apple, 55, Iphone x, 0));// 删brandMapper.deleteById(2);// 改brandMapper.update(new Brand(1, No.1, 华为No.1, 66, 遥遥领先2.0,0));// 查ListBrand brandList brandMapper.selectAll();System.out.println(brandList);sqlSession.commit();sqlSession.close();
}
3输出结果
运行前 运行后