1. Mybatis都有哪些Executor执行器?之间的区别为?
有三种基本的执行器:SimpleExecutor ReuseExecutor BatchExecutor
- SimpleExecutor:每执行一次update、select,就开启一个statement对象,用完立刻关闭
- ReuseExecutor:执行update,select,以sql作为key查找statement对象,存在就使用,不存在就创建,用完后不关闭statement对象,而是放置在Map<String, statement>中,供下一次使用。
- BatchExecutor:执行update(批处理不包括select),将所有sql都添加到批处理中,等待统一执行
2. #{ } 和 ${ }
- #{}:占位符号,可以防止sql注入(替换结果会增加单引号‘’,类型转换),可接收简单类型或pojo属性值。 如果传输单个简单类型值,#{}括号中可以是value或其它名称。
- ${}:sql拼接符号(在预编译之前已被变量替换了,不会增加单引号‘’,存在sql注入问题), 可以接收简单类型值或pojo属性值,无论传什么类型,{}中只能是value
Select * from emp where name = #{employeeName} --> Select * from emp where name = 'Smith';
Select * from emp where name = ${employeeName} --> Select * from emp where name = Smith;
3. 如何获取表中 auto-increment 自增主键的值?
方式一:增加一个用户并返回主键id
<insert id="saveOne" parameterType="com.buwei.entity.User" >
INSERT into user(name, password) value(#{name},#{password})
<selectKey keyProperty="id" order="AFTER" resultType="int">
select last_insert_id()
</selectKey>
</insert>
方式二
<insert id="saveOne" parameterType="com.buwei.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT into user(name, password) value(#{name},#{password})
</insert>
4. 常见的动态标签:8个
- if 、choose、when、otherwize(后三者组合使用)
- foreach:遍历查询
- where:简化where条件判断,能智能的处理 and or ,至少有一个条件符合的时候,才会插入where语句并且会将条件语句前的 and 去掉。
- trim :对包含的内容加上 prefix 或 suffix 等
- set :主要用于更新时,update 表名 set 字段名=新值,set标签放入update标签内部,用于动态包含需要更新的列,而舍去其它的。
<select id="selectEmployeeList" resultType="com.worldly.config.entity.Employee">
select * from t_emp e
<where>
<if test="name!=null and name!=''">
and e.emp_name=#{name,jdbcType=VARCHAR} [and]
</if>
<if test="dep!=null">
and e.emp_dep=#{dep.id,jdbcType=INTEGER}
</if>
</where>
</select>
上例中,若第一个if 为真,则把该 if 中的 and 去掉,若上述红色存在,则出现错误,需要用trim标签
5. SQL注入:
sql注入攻击就是输入参数未经过滤,直接拼接到sql语句中,解析执行,达到预想之外的行为,即执行恶意SQL语句。
- 可将任意SQL代码插入数据库查询,使攻击者能够完全控制数据库服务器。
- 可绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;
- 可使用SQL注入来添加,修改和删除数据库中的记录。
注入实例:
正常情况下,
select * from people where name = '123' and passwd='123';
情况1: 但是如果在用户名框中输入:‘ or 1=1#’,密码随便输入,也可正常登录,如下:
select * from people where name = ' or 1=1#' and passwd='546';
等价于
select * from people where name = ' or 1=1' ;
#可以注释掉后面的SQL语句
情况2:拼接sql
String sql = "select * from user where username = ' ' and password = ' '";
把pwd传入1’ or ‘1’ = '1,前面的1可以随便填,任意输入密码,都可正确登录。
补:PreparedStatement的参数化防注入:
因为SQL语句在程序运行前已经进行了预编译,在使用参数化查询时,数据库不会将参数的内容视为SQL的一部分来处理,而是在数据库完成SQL指令编译后,才套用参数运行,即使参数里有敏感字符如 or ‘1=1’,数据库会作为一个字段的属性值来处理而不会作为一个SQL指令。
6. Mapper实现2种方式
6.1 传统方式
// 加载配置文件
Reader reader = Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
String statement = "lianxi.personMapper.queryPersonById";
Person person = session.selectOne(statement, 1);
6.2. Mapper动态代理方式
Reader reader = Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
//动态代理方式:从sqlSession中获取Mapper接口的代理对象
PersonMapper personMapper = session.getMapper(PersonMapper.class);
Person person = personMapper.queryPersonById(1);
session.close();
使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类。动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定。
7. SqlMapConfig.xml配置文件
常用标签:
properties(属性):引用java属性文件中的配置信息
<!-- 是用resource属性加载外部配置文件 -->
<properties resource="db.properties">
<!-- 如果外部配置文件有该属性,则内部定义属性被外部属性覆盖 -->
<property name="jdbc.username" value="root123" />
</properties>
typeAliases(类型别名)
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="cn.itcast.mybatis.pojo.User" />
<!-- 批量别名定义,扫描整个包下的类,别名为首字母小写的类名(大小写不敏感) -->
<package name="cn.itcast.mybatis.pojo" />
</typeAliases>
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
<!--事务提交方式
JDBC:利用JDBC方式处理事务(commit rollback close)
MANAGED:将事务交由其他组件去托管(spring jobss) 默认会关闭连接-->
<transactionManager type="JDBC"/>
<!--数据源类型
UNPOOLED:传统的JDBC模式,每次访问数据库,均需要打开、关闭数据库
POOLED:使用数据库连接池
JNDI:从tomcat中获取一个内置的数据库连接池-->
<dataSource type="POOLED">
<!-- 配置数据库信息 -->
<property name="driver" value="${mysqlDriver}"/>
<property name="url" value="${mysqlURL}"/>
<property name="username" value="${mysqlUser}"/>
<property name="password" value="${mysqlPaw}"/>
</dataSource>
mappers(映射器)
<mappers>
<!-- 加载映射文件 -->
<!-- <mapper resource="org/mapper/personMapper.xml"/> -->
</mappers>
注: MyBatis通过工厂模式来创造数据源DataSource,定义了抽象的工厂接口DataSourceFactory接口,通过getDataSource()方法返回数据源。