MyBatis 的配置文件包含了影响 MyBatis 行为甚深的 设置(settings)和属性(properties)信息。文档的 顶层结构如下:
configuration 配置
properties 属性:可以加载properties配置文件的信息
settings 设置:可以设置mybatis的全局属性
typeAliases 类型命名
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
environment 环境变量
transactionManager 事务管理器
dataSource 数据源
databaseIdProvider 数据库厂商标识
mappers 映射器
1.为全局配置文件绑定dtd约束:
1)联网会自动绑定
2)没网的时候【/org/apache/ibatis/builder/xml/mybatis-3-config.dtd】:解压mybatis 的jar包然后在eclipse中绑定
2. properties属性
<configuration> <!-- 1.mybatis可以使用properties来引入外部properties配置文件的内容 resource:引入类路径下的资源 url:引入网络路径或者磁盘路径下的资源 --> <properties resource="jdbc.properties"></properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> </environments> <!-- 将我们写好的sql映射文件一定要注册到全局配置文件中 --> <mappers> <mapper resource="EmployeeMapper.xml"/> </mappers> </configuration>
3.settings包含很多重要的设置项
setting:用来设置每一个设置
name:设置项名
value:设置项取值
举例:驼峰式命名
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
1).mapUnderscoreToCamelCase:自动完成数据表标准列名和持久化类标准属性名之间的映射。
例如:last_name和lastName
4.typeAliases:【不建议大家使用别名】
作用:A type alias is simply a shorter name for a Java type <!-- typeAliases:别名处理器,可以为我们的java类型起别名,别名不区分大小写 --> <typeAliases> <!-- typeAlias:为某个java类型起别名 type:指定要起别名的类型全类名;默认别名就是类名小写; alias:执行新的别名 --> <typeAlias type="com.neuedu.mybatis.bean.Employee"/> <!-- package:为某个包下的所有类批量起别名 name:指定包名(为当前包以及下面所有的后代包的每一个类都起一个默认别名【类名小写】) --> <package name="com.neuedu.mybatis.bean"/> <!-- 批量起别名的情况下,使用@Alias注解为某个类型指定新的别名 --> </typeAliases> 虽然有这么多的别名可以使用:但是建议大家还是使用全类名,看SQL语句是怎么被封装为JAVA 对象的时候简单!
5.typeHandlers:类型处理器
类型处理器:负责如何将数据库的类型和java对象类型之间转换的工具类
6.environments【用于配置MyBatis的开发环境】
<!–
environments:环境们,mybatis可以配置多种环境,default指定使用某种环境。可以达到快速切换环境。
environment:配置一个具体的环境信息;必须有两个标签;id代表当前环境的唯一标识
transactionManager:事务管理器
type:事务管理器的类型;type=”[JDBC|MANAGED]”),这两个都是别名,在Configuration类中可以查看具体类!但是Spring对事务的控 制才是最终的管理方案!
JDBC:这个配置就是直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务。
MANAGED:这个配置几乎没做什么,它从来不提交和回滚一个连接。而是让容器来管理事务的整个生命周期。
所以综上:这里如果要配置事务处理器,就配置为JDBC。表示使用本地的JDBC事务。
当然也可以自定义事务管理器:只需要和人家一样实现TransactionFactory接口,type指定为全类名。
dataSource:数据源
type:type=”[UNPOOLED|POOLED|JNDI]”
unpooled:无数据库连接池
pooled:有数据库连接池
JNDI:
自定义数据源:实现DataSourceFactory接口,type也是全类名
但是我们也说了,无论是事务管理器的配置还是数据源的配置我们都会使
用spring来做,这里只需要了解一下即可!
–>
<environments default="development"> <environment id="test"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> </environments>
补充:这里可以了解一下如何配置第三方数据源:
定制自己的第三方数据源,如下所示:
要求:需要自定义一个类继承UnpooledDataSourceFactory类,然后在构造器中初始化该对应的dataSource属性,如下所示:
自定义类为: public class C3P0DataSource extends UnpooledDataSourceFactory{ public C3P0DataSource() { this.dataSource = new ComboPooledDataSource(); } } MyBatis的全局配置文件为: <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!-- <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> --> <!-- 配置使用第三方的数据源。属性需要配置为第三方数据源的属性 --> <dataSource type="com.neuedu.mapper.C3P0DataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> 测试类: @Test public void test02(){ //1.获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //2.利用sqlSessionFactory对象创建一个SqlSession对象 SqlSession session = sqlSessionFactory.openSession(); System.out.println(session.getConnection()); //提交事务 session.commit(); } 当然这里需要加入c3p0的jar包; c3p0-0.9.2.1.jar mchange-commons-java-0.2.3.4.jar
7.MyBatis的增删改查标签:
<select></select>
<insert></insert>
<update></update>
<delete></delete>
例如:
<insert id=”saveEmployee”>
INSERT INTO tbl_employee(user_name,email,gender) VALUES(#{userName},#{email},#{gender})
</insert>
databaseIdProvider环境
MyBatis is able to execute different statements depending on your database vendor. The
? MyBatis 可以根据不同的数据库厂商执行不同的语句
<databaseIdProvider type=”DB_VENDOR”>
<property name=”SQL Server” value=”sqlserver”/>
<property name=”DB2″ value=”db2″/>
<property name=”Oracle” value=”” />
<property name=”MySQL” value=”” />
</databaseIdProvider>
Type: DB_VENDOR
–使用MyBatis提供的VendorDatabaseIdProvider解析数据库 厂商标识。也可以实现DatabaseIdProvider接口来自定义。
Property-name:数据库厂商标识
Property-value:为标识起一个别名,方便SQL语句使用
这样在执行不同数据库的时候,就会执行不同数据库的语句了!当然如上所示:当有指定
了databaseId属性的和没有指定databaseId属性的,都有的情况下那就按着有指定databaseId属性的sql语句执行!
所以:databaseId属性:
1).对于不同的数据库,做不同的SQL操作时,SQL语句会有不同。例如:
MySQL和Oracle的分页[mysql分页为limit,而ORACLE分页我们使用rownumber]、插入主键的方式。
MySQL:INSERT INTO tbl_employee(user_name,email,gender) VALUES(#{userName},#{email},#{gender})
ORACLE:INSERT INTO employee(id,user_name,email) VALUES(test.seq.nextval,#{userName},#{email})
所以要想使用ORACLE的自增序列还需要创建一个序列:
如下所示:
create sequence test_seq start with 1;
这样做的好处:在service层只需要调用一个mybatis的方法,而不需要关注底层选择使用的数据库。
employeeDao.insert(employee);
那么:mybatis如何区分使用的是哪个数据库呢?使用databaseId属性
①.在mybatis-config.xml文件中进行配置 <databaseIdProvider type="DB_VENDOR"> <property name="ORACLE" value="oracle"/> <property name="MySQL" value="mysql"/> </databaseIdProvider> ②.在mybatis的映射文件中使用databaseId来区分使用的是哪一个数据库 在mybatis的全局配置文件配置了这个之后,我们只需要在sql映射文件中通过在执行语句的标签上加一个属性databaseId即可! <select id="getEmployeeById" resultType="emp"> select * from tbl_employee where id = #{id} </select> <select id="getEmployeeById" resultType="emp" databaseId="mysql"> select * from tbl_employee where id = #{id} </select> <select id="getEmployeeById" resultType="emp" databaseId="oracle"> select * from tbl_employee where id = #{id} </select> <environments default="dev_mysql"> <environment id="dev_oracle"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.oracle.driver}"/> <property name="url" value="${jdbc.oracle.url}"/> <property name="username" value="${jdbc.oracle.user}"/> <property name="password" value="${jdbc.oracle.passowrd}"/> </dataSource> </environment> <environment id="dev_mysql"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> </environments>
8.mapper映射
<!– mappers:将sql映射注册到全局配置中 –>
<mappers>
<!– mapper:注册一个sql映射
注册配置文件:
resource:引用类路径下的sql映射文件
mybatis/mapper/EmployeeMapper.xml
url:引用网络路径下或者磁盘路径下的sql映射文件
url=”file:///var/mappers/AuthorMapper.xml”
注册接口
class:引用(注册)接口
1.有sql映射文件,映射文件名必须和接口同名,并且放在与接口同一个目录下;
2.没有sql映射文件,所有的sql都是利用注解写在接口上;
推荐:
比较重要的,复杂的Dao接口我们来写sql映射文件
不重要,见到的Dao接口为了开发快速可以使用注解
–>
<mapper resource=”mybatis/mapper/EmployeeMapper.xml”/>
<mapper class=”com.neuedu.mybatis.mapper.EmployeeMapperAnnotation”/>
<!– 批量注册:
1.注解版肯定是没问题的
2.但是对于Mapper.xml映射文件和接口分开的,就需要保证在同一个包下了,否则找不到 –>
<package name=”com.neuedu.mybatis.mapper”/>
</mappers>
补充:MyBatis有基于XML文件的方式也有基于注解的方式,如下所示:
1.使用基于注解的MyBatis映射
1).新建一个XxxMapper接口。通常情况下,Mapper接口和Mapper.xml文件同名,且在同一个包下;
MyBatis在加载Mapper接口的时候也会自动的加载Mapper.xml文件。
2).在该接口中新建方法.
若该方法上没有注解,则mybatis会去对应的Mapper.xml文件中查找和方法名匹配的id的节点进
而执行该节点对应的SQL语句。
3).在方法上使用MyBatis的注解
如下所示:代码和配置如下所示:
Mapper接口为:
public interface EmployeeMapper {
public Employee getEmployeeById(Integer id);
//讲到此处了!此处以下没讲
@Update(“update tbl_employee set user_name = #{userName} where id = #{id}”)
public void updateEmployee(Employee employee);
}
MyBatis的sql映射文件可以没有,MyBatis的全局映射文件可以只用mapper标签加载Mapper接口
<mappers> <!-- resource="com/neuedu/mapper/EmployeeMapper.xml" --> <mapper class="com.neuedu.mapper.EmployeeMapper"/> </mappers>
增删改操作需要提交事务: @Test public void test02(){ //1.获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //2.利用sqlSessionFactory对象创建一个SqlSession对象 SqlSession session = sqlSessionFactory.openSession(); EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); Employee employee = new Employee(1, 1,"张三丰","tangseng@163.com"); mapper.updateEmployee(employee); //提交事务 session.commit(); }
2.获取自增主键值【当向数据库中插入一条数据的时候,默认是拿不到主键的值的, 需要设置如下两个属性才可以拿到主键值!】
对于mysql: <!--设置userGeneratedKeys属性值为true:使用自动增长的主键。使用keyProperty设置把主键值设置给哪一个属性--> <insert id="addEmp" parameterType="com.neuedu.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id" databaseId="mysql"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{gender},#{email}) </insert> 对于ORACLE: <insert id="addEmp" databaseId="oracle"> <!-- order="BEFORE" 设置selectKey中包含的语句先执行。且返回的类型为resultType指定的类型。 再把该值付给keyProperty指定的列 --> <selectKey keyProperty="" resultType="int" order="BEFORE"></selectKey> insert into tbl_employee(id,last_name,email,gender) values(#{id},#{lastName},#{gender},#{email}) </insert>
3.SQL节点:
1).可以用于存储被重用的SQL片段
2).在sql映射文件中,具体使用方式如下:
<insert id="addEmp"> insert into tbl_employee(id, <include refid="employeeColumns"></include>) values(#{id},#{lastName},#{gender},#{email}) </insert> <sql id="employeeColumns"> last_name,email,gender </sql>
五:参数处理
单个参数:mybatis不会做特殊处理
#{参数名}: 取出参数值
多个参数:mybatis会做特殊处理
多个参数会被封装成一个map,
key:param1…paramN,或者参数的索引也可以
value:传入的参数值
#{}就是从map中获取指定的key的值
异常:
org.apache.ibatis.binding.BingdingException:
Parameter ‘id’ not found.
Available parameters are [1,0,param1,param2]
操作:
方法:public Employee getEmployeeAndLastName(Integer id,String lastName);
取值:#{id},#{lastName}
命名参数:明确指定封装参数时map的key:@param(“id”)
多个参数会被封装成一个map,
key:使用@Param注解指定的值
value:参数值
#{指定的key}取出对应的参数值
POJO:
如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;
#{属性名}:取出传入的pojo的属性值
Map:
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map
#{key}:取出map中对应的值
List、Set
#这里面的值也会被封装到map集合中:
key:collection
值:对应的参数值
#{collection[0]}或#{list[0]}
#关于参数的问题:
①.使用#{}来传递参数
②.若目标方法的参数类型为对象类型,则调用其对应的getter方法,如getEmail()
③.若目标方法的参数类型为Map类型,则调用其get(key)
④.若参数是单个的,或者列表,需要使用@param注解来进行标记
⑤.注意:若只有一个参数,则可以省略@param注解
六、参数值的获取
#{}:可以获取map中的值或者pojo对象属性的值
${}: 可以获取map中的值获取pojo对象属性的值
案例演示:
select * from tbl_employee where id = ${id} and last_name = #{lastName}
preparing:select * from tbl_employee where id = 2 and last_name = ?
区别:
#{}:是以预编译的形式,将参数设置到sql语句中,PreparedStatement;防止sql注入
${}:取出的值直接拼装在sql语句中,会有安全问题;
大多情况下,我们取参数的值都应该去使用#{};
原生JDBC不支持占位符的地方我们就可以使用${}进行取值,#{}只是取出参数中的值!
在某些情况下,比如分表、排序;按照年份分表拆分
select * from ${year}_salary where xxx;[表名不支持预编译]
select * from tbl_employee order by ${f_name} ${order} :排序是不支持预编译的!
MyBatis-映射文件select元素
Select元素来定义查询操作。
Id:唯一标识符。
– 用来引用这条语句,需要和接口的方法名一致
parameterType:参数类型。
–可以不传,MyBatis会根据TypeHandler自动推断
resultType:返回值类型。
– 别名或者全类名,如果返回的是集合,定义集合中元素的类型。不能和resultMap同时使用
1.返回类型为一个List
eg:public List<Employee> getEmpsByLastNameLike(String lastName);
<!– resultType:如果返回的是一个集合,要写集合中元素的类型 –>
<selecct id=”getEmpsByLastNameLike” resultType=”com.neuedu.mybatis.bean.Employee”>
select * from tbl_employee where lastName like #{lastName}
</select>
2.返回单条记录为一个Map
<!– 返回一条记录的map:key就是列名,值就是对应的值 –>
public Map<String,Object> getEmpByIdReturnMap(Integer id);
<select id=”getEmpByIdReturnMap” resultType=”map”>
select * from tbl_employee where id = #{id}
</select>
3.返回为一个ResultMap:自定义结果集映射规则
尤其是当数据表的列名和类的属性名不对应的时候:
1.起别名
2.符合下划线转驼峰式命名规范
3.用这里的resultMap
<!– resultMap:自定义结果集映射规则 –>
public Employee getEmployeById(Integer id);
<!– 自定义某个javaBean的封装规则
type:自定义规则的javabean类型
id:唯一id方便引用
–>
<resultMap type=”com.neuedu.mybatis.bean.Employee” id = “myEmp”>
<!–
指定主键列的封装规则
id定义主键列会有底层优化
column:指定是哪一列
property:指定对应的javaBean属性
–>
<id column=”id” property = “id”>
<!– 定义普通列封装规则 –>
<result column=”last_name” property=”lastName”/>
<!–其它不指定的列只要属性名和列名会自动封装,我们只要写resultMap就把全部的映射规则
都写上,不写是因为列名和属性名是对应的 –>
</resultMap>
<!–只需要在映射的地方映射一下就可以了 –》
<select id=”getEmployeById” resultMap=”myEmp”>
select * from tbl_employee where id = #{}
</select>