mybatis总结
foreach元素的属性主要有item,index,collection,open,separator,close。
- item:集合中元素迭代时的别名,该参数为必选。
- index:在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选
- open:foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选
- separator:元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
- close: foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
- collection: 要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:如果User有属性List ids。入参是User对象,那么这个collection = "ids".如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id"
SqlSessionfactoryBuilder:一旦创建了SqlSessionfactory这个类就不需要存在了
SqlSessionfactory:应该在应用执行期间都存在,不要一直重复创建,使用Sping来允许创建支持程序来管理单例SqlSessionfactory的生命周期
SqlSession:每个线程都有自己的SqlSession实例,不能被共享,也是线程不安全
resultMap,resultType,parameterType
、#{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
mybatis 模糊查询like语句该怎么写?
使用#{...}
注意:因为#{...}解析成sql语句时候,会在变量外侧自动加单引号' ',所以这里 % 需要使用双引号" ",不能使用单引号 ' ',不然会查不到任何结果。
使用CONCAT()函数连接参数形式
在mapper中如何传递多个参数?
(1)第一种:
//DAO层的函数
Public UserselectUser(String name,String area);
//对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。
<select id="selectUser"resultMap="BaseResultMap">
select * fromuser_user_t whereuser_name = #{0} anduser_area=#{1}
</select>
(2)第二种: 使用 @param 注解:
public interface usermapper {
user selectuser(@param(“username”) string username,@param(“hashedpassword”) string hashedpassword);
}
然后,就可以在xml像下面这样使用(推荐封装为一个map,作为单个参数传递给mapper):
<select id=”selectuser” resulttype=”user”>
select id, username, hashedpassword
from some_table
where username = #{username}
and hashedpassword = #{hashedpassword}
</select>
(3)第三种:多个参数封装成map
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
//由于我们的参数超过了两个,而方法中只有一个Object参数收集,因此我们使用Map集合来装载我们的参数
Map<String, Object> map = new HashMap();
map.put("start", start);
map.put("end", end);
return sqlSession.selectList("StudentID.pagination", map);
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e; }
finally{
MybatisUtil.closeSqlSession();
}
Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;
原因就是namespace+id是作为Map<String, MapperStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。
但是,在以前的Mybatis版本的namespace是可选的,不过新版本的namespace已经是必须的了。
MyBatis如何分页;如何设置缓存;MySQL分页
)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/> ;
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能;
Executor:MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护;
StatementHandler:封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
ParameterHandler:负责对用户传递的参数转换成JDBC Statement 所需要的参数;
ResultSetHandler:负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;
TypeHandler:负责java数据类型和jdbc数据类型之间的映射和转换;
MappedStatement:MappedStatement维护了一条<select|update|delete|insert>节点的封装;
SqlSource:负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回;
BoundSql:表示动态生成的SQL语句以及相应的参数信息;
Configuration:MyBatis所有的配置信息都维持在Configuration对象之中;
jdbc流程:
-
加载JDBC驱动;(相当于加载jar包)
-
建立并获取数据库连接;(然后根据密码等去链接数据库)
-
创建 JDBC Statements 对象;(链接以后,准备去执行一次请求)
-
设置SQL语句的传入参数;(当然是传入sql语句中需要的参数)
-
执行SQL语句并获得查询结果;(去数据库进行执行)
-
对查询结果进行转换处理并将处理结果返回;(执行以后返回的数据)
-
释放相关资源(关闭Connection,关闭Statement,关闭ResultSet);(当然是关闭链接了)
-
public static List<Map<String,Object>> queryForList(){ Connection connection = null; ResultSet rs = null; PreparedStatement stmt = null; List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>(); try { // 加载JDBC驱动 Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); String url = "jdbc:oracle:thin:@localhost:1521:ORACLEDB"; String user = "trainer"; String password = "trainer"; // 获取数据库连接 connection = DriverManager.getConnection(url,user,password); String sql = "select * from userinfo where user_id = ? "; // 创建Statement对象(每一个Statement为一次数据库执行请求) stmt = connection.prepareStatement(sql); // 设置传入参数 stmt.setString(1, "zhangsan"); // 执行SQL语句 rs = stmt.executeQuery(); // 处理查询结果(将查询结果转换成List<Map>格式) ResultSetMetaData rsmd = rs.getMetaData(); int num = rsmd.getColumnCount(); while(rs.next()){ Map map = new HashMap(); for(int i = 0;i < num;i++){ String columnName = rsmd.getColumnName(i+1); map.put(columnName,rs.getString(columnName)); } resultList.add(map); } } catch (Exception e) { e.printStackTrace(); } finally { try { // 关闭结果集 if (rs != null) { rs.close(); rs = null; } // 关闭执行 if (stmt != null) { stmt.close(); stmt = null; } if (connection != null) { connection.close(); connection = null; } } catch (SQLException e) { e.printStackTrace(); } } return resultList; }
-
第一步优化:连接获取和释放
-
第二步优化:SQL统一存取(配置在mapper)
-
第三步优化:传入参数映射和动态SQL(if,choose、when、otherwise、trim、where、set、foreach)
-
第四步优化:结果映射和结果缓存
-
解决重复SQL语句问题
- MyBatis和数据库的交互有两种方式:使用传统的MyBatis提供的API;使用Mapper接口;
缓存机制
为了提高数据利用率和减小服务器和数据库的压力,MyBatis 会对于一些查询提供会话级别的数据缓存,会将对某一次查询,放置到SqlSession 中,在允许的时间间隔内,对于完全相同的查询,MyBatis会直接将缓存结果返回给用户,而不用再到数据库中查找
-
调用SqlSessionFactoryBuilder对象的build(inputStream)方法;
-
SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;
-
SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法;
-
XMLConfigBuilder对象返回Configuration对象;
-
SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;
-
SqlSessionFactoryBuilder返回 DefaultSessionFactory对象给Client,供Client使用。
-
SqlSessionFactoryBuilder :SqlSessionFactory的构造器,用于创建SqlSessionFactory,采用了Builder设计模式
Configuration :该对象是mybatis-config.xml文件中所有mybatis配置信息
SqlSessionFactory:SqlSession工厂类,以工厂形式创建SqlSession对象,采用了Factory工厂设计模式
XmlConfigParser :负责将mybatis-config.xml配置文件解析成Configuration对象,共SqlSessonFactoryBuilder使用,创建SqlSessionFactory
-
①、编写Mapper 接口和Mapper 映射文件;②、创建SqlSessionFactory;③、通过SqlSessionFactory 创建SqlSession;④、调用SqlSession 执行数据库操作;⑤、调用session.commit() 提交事务;⑥、调用session.close() 关闭会话。
ORM模型
SqlSessionFactoryBuilder(构造器):它会根据配置信息或者代码来生成SqlSessionFactory
SqlSessionFactory:依靠工厂来生成SqlSession(会话)
SqlSession:是一个既可以发送SQl去执行并返回结果,也可以获取Mapper的接口
SQL Mapper:它是MyBatis新设计的组件,它是由一个java接口和xml文件(或注解)构成的,需要给出对应的SQL和映射规则,它负责发送SQL去执行。并返回结果
SqlSessionFactory两个实现类:SQLSessionManager和DefaultSqlSessionFactory,目前使用的是DefaultSqlSessionFactorySqlSession的用途(1)获取映射器,让映射器通过命名空间和方法名称找到对应的SQL,发送给数据库执行后返回结果(2)直接通过命名信息去执行SQL返回结果,这是IBatis版本留下的方式,在SqlSession层,我们可以通过update,insery,select,delete方法,带上SQL的id来操作XML中配置好的SQL,从而完成我们的工作,与此同时它也支持事务,通过commit,rollback方法提交或者回滚事务
String resource = "mybatis-config.xml";
//1.流形式读取mybatis配置文件
InputStream stream = Resources.getResourceAsStream(resource);
//2.通过配置文件创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
//3.通过SqlSessionFactory创建sqlSession
SqlSession session = sessionFactory.openSession();
//4.通过SqlSession执行Sql语句获取结果
List<User> userList = session.selectList("selectAll");
System.out.println(userList.size());
SqlSessionFactoryBuilder,SqlSessionFactory,SqlSession,SQL Mapper的生命周期
select元素配置(id唯一,parameterType(定义参数类型),resultType[不能和resultMap同时使用],resultMap)
<select id="countFirstName" parameterType="string" resultType"int">参数使用Map和@Param(“roleName”)String roleName和javaBean
choose,when,otherwise
动态代理分为两种,一种是JDK反射机制提供的代理,另一种是CGLIB代理。在jdk提供的代理,我们必须要提供接口,而CGLIB不需要提供接口
-
-