MyBatis-全局配置文件

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>

原文地址:https://www.cnblogs.com/lc-java/p/7488069.html