MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis的持久化解决方案是将用户从原始的JDBC访问中解放出来,用户只需要定义需要操作的SQL语句,无须关注底层的JDBC操作,就可以以面向对象的方式来进行持久化层操作.底层数据库连接的获取,数据访问的实现,事务控制等都无须用户关心。
mybatis的使用- 导入maven依赖
org.mybatis mybatis 3.5.2
- 编写核心配置文件
- 编写mybatis工具类
public class MybatisUtils {
static private SqlSessionFactory build;
static {
try {
//获取sqlSessionFactory对象
String resource = "src/main/resources/mybatis-config.xml";
InputStream io = Resources.getResourceAsStream(resource);
build = new SqlSessionFactoryBuilder().build(io);
} catch (IOException e) {
e.printStackTrace();
}
}
//接下来可以通过sqlSessionFactory对象获取sqlSession
public static SqlSession getSqlSession(){
return build.openSession();
}
}
介绍SqlSessionFactory:
SqlSessionFactory是MyBatis的关键对象。SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象类获得。
SqlSessionFactoryBuilder可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实,顾名思义SqlSessionFactory就是创建SqlSession的工厂。
介绍SqlSession:
SqlSession是MyBatis的关键对象,SqlSession中包含了执行SQL的所有方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行被映射的SQL语句.
编写代码测试- Dao层接口
public interface UserDao {
List getUserList();
}
- 编写Mapper.xml配置实现接口
select * from user where id = 1;
注意点:每一个Mapper都必须在Mybatis核心配置文件中注册(类似servlet)
resource用于绑定文件夹下的xml,
class绑定接口
由于maven约定大于配置,可能会出现mybatis-config.xml核心文件找不到的问题,在maven中加入静态资源过滤就可以解决
src/main/java ***.xml true src/main/resources ***.xml true
插入一则自己遇到的bug:
org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 14; 1 字节的 UTF-8 序列的字节 1 无效。
原因是编码方式设置成了默认的UTF-8,改成UTF8就正常了
测试类:
public class UserDaoTest {
@Test
public void Test01(){
//通过工具类获取sqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 反射获取接口
UserDao mapper = sqlSession.getMapper(UserDao.class);
// 执行方法
List userList = mapper.getUserList();
for(User u:userList){
System.out.println(u);
}
}
}
CRUD实现
- namesapce
namesapce中的包名必须要和Dao接口中的保持一致
select选择,查询数据
- id:对应绑定接口中的方法
- resultType:对应执行sql后返回的数据类型
- parameterType:对应传进来参数的类型(传参用#{}来取参数)
如果想要传递多种不同类型的参数,可以通过@param注解来实现,如:
public User selectUser(@Param("userName") String name, int @Param("deptId") deptId);
#{}里面的名称直接对应注解@Param括号里面修饰的名称。
或者使用map集合一一对应传参
对于传入参数为对象类型的,直接使用属性.属性.属性获取值 , 如: #{xx.xx.xx};
增删改的操作类似,就点到为止
Mapmapper.xml:
# 参数为map集合,直接取存放在集合中的元素即可 insert into mabatis.user (id, name, pwd) VALUES (#{userId},#{userName},#{userPwd});
UserMapper:
void addUser(Mapmap);
代码测试:
@Test
public void addUsertest(){
//通过工具类获取sqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 反射获取接口
UserDao mapper = sqlSession.getMapper(UserDao.class);
// 执行方法
Map map = new HashMap();
map.put("userId",5);
map.put("userName","吴诗怡");
map.put("userPwd","541541");
mapper.addUser(map);
sqlSession.commit();
sqlSession.close();
}
模糊查询通配符要写在参数里面,防止SQL注入问题。
配置解析 环境配置(environments)不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:
每个数据库对应一个 SqlSessionFactory 实例
properties文件配置注意xml规定了标签顺序
优先使用外部配置文件
可用注解起别名 @Alias("要起的别名") 注意需要在mapper.xml配置文件中配置扫描包
mybatis中有一些默认的别名(详情见文档)
映射器有4种方式,见官方文档:
映射器(mappers)既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:
尽量保证接口和xml文件在一个包下
作用域 SqlSessionFactoryBuilder这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
SqlSessionFactorySqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 是一种坏习惯。
因此 SqlSessionFactory 的最佳作用域是应用作用域。
最简单的就是使用单例模式或者静态单例模式。
SqlSession用完就马上关
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。
结果集映射resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
使用resultMap实现,id对应映射的方法,type表示需要和数据库字段做映射的类,即把type表示的实体类中的属性映射到数据库中的字段
日志
数据库出错的排错工具:日志工厂
-
SLF4J
-
LOG4J
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING(标准日志输出)
-
NO_LOGGING
在mybatis-config.xml核心配置文件中设置setting
LOG4Jmaven仓库包
log4j
log4j
1.2.17
编写配置文件
配置根Logger等等,如:
log4j.rootLogger = level,appenderName1,appenderName2, .....
level是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别,默认优先级:
ALL < DEBUG < INFO Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来 appenderName是日志信息输出位置,可以同时指定多个输出目的地 其他详情配置自个网上看: LOG4J框架配置文件详解_ 简单使用 使用方法类似于使用类 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。 复杂操作用xml,简单SQL语句可以用注解 在mabatis-config.xml中用class绑定 绑定需要用到注解的类,如: 接口配置: 其中Student对象的属性中包含Teacher对象 过程:先查询出Student对象,再用查出来的Student对象的tid属性再嵌套查询teacher对象 这种方式虽然很简单,但在大型数据集或大型数据表上表现不佳。这个问题被称为“N+1 查询问题”。 概括地讲,N+1 查询问题是这样子的: 这个问题会导致成百上千的 SQL 语句被执行。有时候,我们不希望产生这样的后果。 好消息是,MyBatis 能够对这样的查询进行延迟加载,因此可以将大量语句同时运行的开销分散开来。 然而,如果你加载记录列表之后立刻就遍历列表以获取嵌套的数据,就会触发所有的延迟加载查询,性能可能会变得很糟糕。 不用对SQL进行处理,直接联表查询。将结果查询出来后对结果集进行处理 个人推荐按结果嵌套映射,按查询嵌套。。。。痛苦面具 一个老师对应多个学生: Mapper: 详情见官方文档: mybatis – MyBatis 3 | 动态 SQL 可以使用sql标签支持SQL语句复用,用的时候用include标签引用就彳亍 foreach标签遍历集合,item表示集合内的元素项,还有开始符,分割符,结束符等配置 mybatis默认开启一级缓存,SqlSession级别,SqlSession被销毁缓存就失效了。作用范围是从Sqlsession被创建到被销毁 也可手动清理缓存 二级缓存需要手动配置,是namespace级别的,在当前mapper.xml中有效。使用cathe标签(详见官方文档)要用的话最好在核心配置文件中显式配置。 缓存查询顺序:用户发起请求–>查二级缓存–>查一级缓存–>查数据库 内存中的临时数据 mybatis默认开启一级缓存,SqlSession级别,SqlSession被销毁缓存就失效了。作用范围是从Sqlsession被创建到被销毁 也可手动清理缓存 二级缓存需要手动配置,是namespace级别的,在当前mapper.xml中有效。使用cathe标签(详见官方文档)要用的话最好在核心配置文件中显式配置。 缓存查询顺序:用户发起请求–>查二级缓存–>查一级缓存–>查数据库#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/zhang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
static Logger logger = Logger.getLogger([需要使用的类的名字].class);
@Select("select * from user where id > 0")//sql的语句同xml文件
List
多对一的处理
一对多的处理
public class Teacher {
private long id;
private String name;
private List
动态SQL



