网站导航设计,wordpress幻灯片制作,论坛wordpress还是,制造业营销外贸网站建设文章目录 概述比较配置写xml加载上面配置并执行加载配置的方法方式一 执行方法方式一方式二(MyBatis映射器) 写配置文件的映射文件设置对象的别名#xff08;简写#xff09;获取自动生成的主键 查询结果和java的映射规则基本类型映射#xff1a;简单对象映射#xff1a;嵌… 文章目录 概述比较配置写xml加载上面配置并执行加载配置的方法方式一 执行方法方式一方式二(MyBatis映射器) 写配置文件的映射文件设置对象的别名简写获取自动生成的主键 查询结果和java的映射规则基本类型映射简单对象映射嵌套对象映射忽略大小写下划线转驼峰 构造器映射注解映射方式一方式二 三个关键类的生命周期1.1.SqlSessionFactoryBuilder1.2.SqlSessionFactory1.3.SqlSession 日志日志等级配置打印入参 #{}与${}比较使用的场景 动态SQLifchoose、when、otherwisetrim、where、setforeach(批量操作)bind java API_MyBatisSqlSessionFactoryBuilderResources 工具类SqlSessionFactorySqlSession SQL类踩坑 概述
前生IBatis,现在很多包都是IBatis。
比较
MyBatis与JPA MyBatis更加灵活自己写sql,可以Sql优化 JPA不行因为自己生成SQL
配置
写xml
取名mybatis-config.xml连接数据库
?xml version1.0 encodingUTF-8 ? 声明
!DOCTYPE configuration PUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd 约束
!--根元素里面就是Mybatis配置--
configuration
!-- 环境配置数据库的配置环境(怎么连接数据库) 可以配置多个环境对象 environment多个数据库的连接配置可以通过 defaultdevelopment 来切换默认的环境
--environments defaultdevelopmentenvironment iddevelopment
!-- 事务管理器typeJDBC使用JDBC的事务管理 JdbcTransaction --transactionManager typeJDBC/
!-- 数据源配置 POOLED 连接池对应 PooledDataSource--dataSource typePOOLEDproperty namedriver valuecom.mysql.jdbc.Driver/property nameurl valuejdbc:mysql:///mybatis/property nameusername valueroot/property namepassword value123456//dataSource/environment!-- environment idtest--
!-- ... --
!-- /environment--/environments
!--映射配置标注清楚sql语句写在哪里--mappersmapper resource自己映射文件的目录xml文件//mappers
/configuration环境可以设置多个连接不同的数据库起不同的作用可以将不同的用途设置给id,如测试开发生产环境等。事务简称tx。
改进一下 数据库的连接配置可以提出来 写成一个jdbc.properties配置配置加一个
!-- 加载properties--properties resourcejdbc.properties /transactionManager typeJDBC/dataSource typePOOLED!--通过k取value--property namedriver value${jdbc.driver}/property nameurl value${jdbc.url}/property nameusername value${jdbc.username}/property namepassword value${jdbc.password}//dataSource/environment再改进一下 3.5.2开始之后可用 如果属性 ‘username’ 没有被配置‘username’ 属性的值将为 ‘ut_user’ 原理 ${tableName ! null ? tableName : ‘global_constants’} dataSource typePOOLEDproperty nameusername value${username:ut_user}/ /dataSourceproperties resourceorg/mybatis/example/config.properties!-- 开启上面的功能 可在value中自定义修改分隔符写了就换--property nameorg.apache.ibatis.parsing.PropertyParser.enable-default-value valuetrue/ !-- 启用默认值特性 --
/properties加载上面配置并执行
会话工厂建造者建造会话工厂会话工厂又生产会话用会话去操作 在会话执行的方法通过命名空间id获取。 执行的的各种方法都是在sqlSession类中
命名空间可以提出去设置成常量 建造工厂可以提出去创建一个utils sqlSession用完要关掉其他的不用 openSession()无参就需要手动提交 .commit()如果传了true那么就自动提交不用commit()
加载配置的方法
方式一 执行方法
方式一 注意:方式一namespace和Xxxmapper可以不同但是在sqlssion.xxx,中和xml文件一致就可以了
方式二(MyBatis映射器)
加一个接口和命名空间一样与xml文件相连
public interface CustomerMapper {ListCustomer selectCustomer();
}或者注解
public interface CustomerMapper {Select( SELECT id,user_name,age,pwd,money from users)ListCustomer selectCustomer();
}//selectList sqlSession.selectList(NAMESPACE selectCustomer);//替换成下面的这个语句CustomerMapper mapper sqlSession.getMapper(CustomerMapper.class);selectList mapper.selectCustomer();原理 动态代理用cglib动态代理实现的。 service层中的改变
写配置文件的映射文件
写了这个还需要写一个命名空间接口其中的方法对应id的值那个接口也可以不用写写是为了和service结合这里不用结合就可以不用写这个命名空间在这里可以写此个xml文件名 还需要写一个实体类对应查询回来的数据对应resultType的值 没有配置简写就要写完全。
Mapper文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
!--namespace:命名空间 sql坐标SQL在哪儿规范写法一般写这个mapper.xml所在的包的路径
--
mapper namespace接口需要实现的方法的接口MxxMapper,
!-- 查询语句 id是sql的id,在同一个mapper.xml中必须唯一如何精准的找到一个SQL namespaceidresultType:返回的结果的实体类
--select id唯一标识符对应的是命名空间接口中的某个方法 resultType返回的实体类路径 ParameterType参数类型/select/mapper设置对象的别名简写
自己写的类配置别名 在MyBatis-Config.xml配置
!-- 加载properties--properties resourcejdbc.properties /typeAliases!--给单个类设置别名 alias的值可以任意写--typeAlias typecom.ronghuanet.mybatis.domain.Product aliasProduct /!--扫描包这个包下面的所有类都设置一个别名--
!-- package namecom.ronghuanet.mybatis.domain/--/typeAliases.........框架含有的
获取自动生成的主键
先设置这个 !--自动生成主键赋值给对象的对应的成员变量再插入进去--insert ...... useGeneratedKeystrue 开启自动生成主键 keyColumnid 数据库主键列,告诉框架id列 keyPropertyid 与数据库对应主键的成员变量/insert再插入之后在获取主键就可以获取到。
查询结果和java的映射规则
注意查询返回的类型必须要有无参构造。
可以映射的东西 Java 基本数据类型、自定义的 Java 类以及 java.util.MapHashMap等
基本类型映射
当查询的结果只有一个列时MyBatis 可以将该列的值直接映射到一个基本数据类型或包装类如 int、String、Long 等。
简单对象映射
当查询的结果包含多个列时可以通过在映射文件中使用 标签来定义对象映射规则。通过指定结果列和 Java 对象属性的对应关系MyBatis 将查询结果映射到一个简单对象POJO中。 resultMap idbaseResultMap唯一表示符 type映射的java类型id columnid 数据库列 propertyid 对象属性 /result columnproduct_name 数据库列 propertyproductName 对象属性//resultMap将resultType改成resultMap
嵌套对象映射
如果查询的结果包含多个表的数据可以使用 和 标签来进行嵌套对象映射。通过在映射文件中定义关联关系MyBatis 可以将查询结果映射到一个复杂的对象图中包含多个对象之间的关联关系。 注意 最好逐步建立结果映射。单元测试可以在这个过程中起到很大帮助。 从最简单的形态开始逐步迭代。而且别忘了单元测试 有时候框架的行为像是一个黑盒子无论是否开源。因此为了确保实现的行为与你的期望相一致最好编写单元测试。 并且单元测试在提交 bug 时也能起到很大的作用。
使用时避免使用 n1 原理list肯很大list是主要 需要展示的对象
忽略大小写
MyBatis 在进行列名和属性名的匹配时默认是忽略大小写的。这意味着列名和属性名在大小写上不区分可以自动匹配成功。 原理:MyBatis 在进行自动映射时会根据 Java 对象中的 Setter 方法即属性的设置方法来确定属性名并将查询结果集中的列值赋给该属性。具体来说MyBatis 会按照以下规则生成属性名 setName(去掉set)-Name(N变小写)-name 与数据库的字段列一样就好了
下划线转驼峰
MyBatis 支持将下划线分隔的列名转换为驼峰式命名的属性名。例如如果查询结果的列名是 user_name而对象中的属性名是 userName 则 MyBatis 可以自动将其映射起来。这个需要开启
settingssetting namemapUnderscoreToCamelCase valuetrue//settings类型处理器在自动映射时如果数据库中的数据类型和 Java 对象属性的类型不匹配MyBatis 会尝试使用类型处理器进行转换。
构造器映射
除了使用默认的无参构造器来创建对象MyBatis 还支持使用带参构造器来创建对象并通过列值来调用相应的构造器。 Java 对象必须具有带参构造器要使用构造器映射Java 对象必须定义了带参数的构造器。 构造器的参数顺序和类型要与查询结果的列对应构造器的参数顺序和类型必须和查询结果的列一一对应。MyBatis 会根据列名和构造器参数名的匹配关系来确定调用哪个构造器。
resultMap iduserResultMap typeUserconstructoridArg columnid javaTypeLong /arg columnusername javaTypeString /arg columnage javaTypeInteger //constructor
/resultMap
注解映射
方式一
除了 XML 配置文件外MyBatis 还支持使用注解来定义对象映射规则。通过在 Java 对象上添加 Results 和 Result 注解可以实现对象与查询结果的映射。
public class User {Result(column user_id, property userId)private Long userId;Result(column username, property username)private String username;// 省略 getter 和 setter 方法
}或者
Results({Result(column user_id, property userId),Result(column username, property username)
})
Select(SELECT user_id, username FROM users)
ListUser getUsers();
方式二
在注解映射中我们可以使用注解来描述实体类Java 对象与数据库表的对应关系以及实体类的属性与表字段的对应关系。通过这些注解的配置框架可以自动完成数据库的增删改查操作并将查询结果映射到对应的 Java 对象中。
Entity用于标识实体类表示该类与数据库表对应。Table用于指定实体类与数据库表的映射关系可以指定表名、schema 等信息。Column用于指定实体类的属性与数据库表字段的映射关系可以指定字段名、长度、默认值等信息。Id用于指定实体类的主键属性表示该属性是数据库表的主键。GeneratedValue用于指定主键的生成策略如自增长、UUID 等。Transient用于指定实体类的属性不与数据库表字段进行映射即忽略该属性。
Entity
Table(name user)
public class User {IdGeneratedValue(strategy GenerationType.IDENTITY)private Long id;Column(name username)private String username;Column(name age)private Integer age;// 省略 getter 和 setter 方法
}
三个关键类的生命周期
1.1.SqlSessionFactoryBuilder
这个类可以被实例化使用和丢弃。一旦你创建了 SqlSessionFactory 后这个类就不需要存在了。因为工厂创建了工人就不需要了
1.2.SqlSessionFactory
一旦被创建SqlSessionFactory 应该在你的应用执行期间都存在因为是工厂需要不断创建sqlsession它应该是单例的也是线程安全的并且随着应用的创建而创建随着应用的销毁而销毁。SqlSessionFactory 中存储了1.xml基本信息2.连接池对象, 3.二级缓存。SqlSession是通过SqlSessionFactory来创建的。
1.3.SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不能被共享也是线程不安全的。因此最佳的范围是请求或方法范围。它内部存储的东西**1.连接对象 2.一级缓存。**
日志
日志等级
trace(最小全部都要打印) ,debug调试 , info提示 , warn(警告) ,error错误
配置
创建一个log4j的配置文件 将配置文件放置在类路径下将创建好的 Log4j 配置文件放置在项目的类路径下MyBatis 会在初始化过程中自动加载类路径下的 Log4j 配置文件并根据配置文件中的设置来进行日志输出 一部分配置配什么查什么
#全局日志配置
log4j.rootLogger info,console#输出局部的日志信息(自己的包中的日志打印方式)
log4j.logger.com.wjTRACE 自己哪里的数据操作需要打印操作### 配置输出到控制台
log4j.appender.console org.apache.log4j.ConsoleAppender
### 使用System.out打印日志
log4j.appender.console.Target System.out
### 指定日志的格式布局(日志是有格式的)
log4j.appender.console.layout org.apache.log4j.PatternLayout
### 日志的打印格式
log4j.appender.console.layout.ConversionPattern %d{ABSOLUTE} %5p %c{1}:%L - %m%n打印入参
进入每一个方法时都可以写这样可以更好的理解程序的执行过程和传入的数据情况。
#{}与${}比较
其实#{}的底层就是使用的 “?”占位符的方式来拼接SQL而${}使用的是直接把拼接到SQL中
看看有什么不一样 select idselectById parameterTypelong resultType...Employeeselect * from employee where id #{id}/select
-----------------------------------------------------------------------------------------------------select idselectById parameterTypelong resultType...Employeeselect * from employee where id ${id}/select直接拼接会调用 g e t t e r 方法去获取值会用属性值用于 D D L 可以用再 {} 直接拼接 会调用getter方法去获取值会用属性值 用于DDL 可以用再 直接拼接会调用getter方法去获取值会用属性值用于DDL可以用再{group by} #{} 占位符 不用要用getter方法获取 DQL
使用的场景
${} 适用于静态的表名、列名等以及一些需要进行复杂表达式的参数替换使用时需要注意 SQL 注入风险。
#{} 主要用于替换动态生成的参数值通常在查询条件、插入或更新的参数中使用。提高安全和速度。
Select(select * from user where ${column} #{value})
User findByColumn(Param(column) String column, Param(value) String value);动态SQL
if
可以匹配多个分支 if testtitle ! nullAND title like #{title}/if注意 如果用 这是一个标签开始符号 要改成 转义符 如果用要用where 解决一 在第一个if标签中加where 再在最开始的表名后面 11 但是这样就不会用索引了 解决二 直接用where标签把他们嵌套进去
choose、when、otherwise
只会选择最先匹配的一个分支执行匹配后不会再进行匹配了
select idfindActiveBlogLikeresultTypeBlogSELECT * FROM BLOG WHERE state ‘ACTIVE’choosewhen testtitle ! nullAND title like #{title}/whenwhen testauthor ! null and author.name ! nullAND author_name like #{author.name}/whenotherwiseAND featured 1/otherwise/choose
/selecttrim、where、set
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且若子句的开头为 “AND” 或 “OR”where 元素也会将它们去除。 trim通过自定义 trim 元素来定制 where 和set元素的功能。 set 元素可以用于动态包含需要更新的列忽略其它不更新的列。 例如:set
这个set 元素会动态地在行首插入 SET 关键字并会删掉额外的逗号setif testusername ! nullusername#{username},/ifif testpassword ! nullpassword#{password},/ifif testemail ! nullemail#{email},/ifif testbio ! nullbio#{bio}/if/set等价trim prefixSET suffixOverrides,...
/trim例如:WHERE 若子句的开头为 “AND” 或 “OR”where 元素也会将它们去除。whereif teststate ! nullstate #{state}/ifif testtitle ! nullAND title like #{title}/ifif testauthor ! null and author.name ! nullAND author_name like #{author.name}/if/where等价
trim prefixWHERE prefixOverridesAND |OR ...
/trimforeach(批量操作)
数据最多不能超过4M 如 批量删除
常见使用场景是对集合进行遍历尤其是在构建 IN 条件语句的时候 注意当使用 Map 对象或者 Map.Entry 对象的集合时index 是键item 是值。
它允许你指定一个集合声明可以在元素体内使用的集合项(集合里的对象)item和索引index变量
。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符
WHERE ID inforeach itemitem indexindex collectionlistopen( separator, close)#{item}/foreach如 批量插入需求 上下不匹配
bind
给一段语句设置一个变量 bind 元素允许你在 OGNL 表达式以外创建一个变量并将其绑定到当前的上下文 OGNL 表达式的作用可以存取对象的属性和调用对象的方法通过OGNL 表达式可以迭代获取对象的结构图
select idselectBlogsLike resultTypeBlogbind namepattern value% _parameter.getTitle() % /SELECT * FROM BLOGWHERE title LIKE #{pattern}
/selectjava API_MyBatis
SqlSessionFactoryBuilder
自我感觉这个类不太重要 SqlSessionFactoryBuilder 有五个 build() 方法每一种都允许你从不同的资源中创建一个 SqlSessionFactory 实例。 第一种方法是最常用的它接受一个指向 XML 文件
SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)
SqlSessionFactory build(Configuration config)Resources 工具类
URL getResourceURL(String resource)
URL getResourceURL(ClassLoader loader, String resource)
InputStream getResourceAsStream(String resource)
InputStream getResourceAsStream(ClassLoader loader, String resource)
Properties getResourceAsProperties(String resource)
Properties getResourceAsProperties(ClassLoader loader, String resource)
Reader getResourceAsReader(String resource)
Reader getResourceAsReader(ClassLoader loader, String resource)
File getResourceAsFile(String resource)
File getResourceAsFile(ClassLoader loader, String resource)
InputStream getUrlAsStream(String urlString)
Reader getUrlAsReader(String urlString)
Properties getUrlAsProperties(String urlString)
Class classForName(String className)SqlSessionFactory
SqlSessionFactory 有六个方法创建 SqlSession 实例。通常来说当你选择其中一个方法时你需要考虑以下几点
事务处理你希望在 session 作用域中使用事务作用域还是使用自动提交auto-commit对很多数据库和/或 JDBC 驱动来说等同于关闭事务支持数据库连接你希望 MyBatis 帮你从已配置的数据源获取连接还是使用自己提供的连接语句执行你希望 MyBatis 复用 PreparedStatement 和/或批量更新语句包括插入语句和删除语句吗
SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();ExecutorType.SIMPLE该类型的执行器没有特别的行为。它为每个语句的执行创建一个新的预处理语句。 ExecutorType.REUSE该类型的执行器会复用预处理语句。 ExecutorType.BATCH该类型的执行器会批量执行所有更新语句如果 SELECT 在多个更新中间执行将在必要时将多条更新语句分隔开来以方便理解
SqlSession
游标Cursor与列表List返回的结果相同不同的是游标借助迭代器实现了数据的惰性加载。
try (SqlSession sqlSession sqlSessionFactory.openSession()) {try (CursorUser cursor sqlSession.selectCursor(com.example.UserMapper.getAllUsers)) {IteratorUser iterator cursor.iterator();while (iterator.hasNext()) {User user iterator.next();// 处理 user 数据}}
}
游标使用游标查询结果不会一次性全部加载到内存中而是通过迭代器逐行获取这可以减少内存占用尤其在处理大型结果集时更为有效。 列表列表返回的方式是将查询结果集全部加载到内存的 List 集合中这使得你可以立即访问整个结果集但也可能导致内存占用较大尤其是在处理大量数据时。列表方式适合于小规模的结果集可以一次性加载并在内存中进行操作。
select 方法的三个高级版本它们允许你限制返回行数的范围或是提供自定义结果处理逻辑通常在数据集非常庞大的情形下使用
E ListE selectList (String statement, Object parameter, RowBounds rowBounds)
T CursorT selectCursor(String statement, Object parameter, RowBounds rowBounds)
K,V MapK,V selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandlerT handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandlerT handler)RowBounds 参数会告诉 MyBatis 略过指定数量的记录并限制返回结果的数量。RowBounds 类的 offset 和 limit 值**只有在构造函数**时才能传入其它时候是不能修改的。
int offset 100; 开始的点
int limit 25; 限制的行
RowBounds rowBounds new RowBounds(offset, limit);数据库驱动决定了略过记录时的查询效率。为了获得最佳的性能建议将 ResultSet 类型设置为 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE SCROLL_SENSITIVE滚动敏感可以接收其他事务对数据的更改 SCROLL_INSENSITIVE滚动不敏感
SQL类
JAVA生成代码
public class UserSqlProvider {
public String getUsers(String username, String email) {return new SQL().SELECT(id, username, email).FROM(users).WHERE().if testusername ! nullAND username #{username}/if.if testemail ! nullAND email #{email}/if.toString();}
}//使用
SelectProvider(type UserSqlProvider.class, method getUsers)
ListUser getUsers(Param(username) String username, Param(email) String email);踩坑
这样写IStudentService studentService new StudentServiceImpl();static {try {SqlSession sqlSession MyBatisUtils.getSqlSession();IDepartmentMapper departmentMapper sqlSession.getMapper(IDepartmentMapper.class);} catch (Exception e) {e.printStackTrace();}}
不能
会报错excutor。。被关闭了IStudentService studentService new StudentServiceImpl();static {try( SqlSession sqlSession MyBatisUtils.getSqlSession()) {IDepartmentMapper departmentMapper sqlSession.getMapper(IDepartmentMapper.class);} catch (Exception e) {e.printStackTrace();}}