MyBatis笔记(一)

1.MyBatis介绍

  1.1 Mybatis由来:

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

  1.2 Mybatis的特点:

Mybatis是一个优秀的持久层框架,它对使用JDBC操作数据库的过程进行了封装,使开发者只关注SQL语句本身,不需要花费精力去处理例如注册驱动、创建connection等jdbc繁杂的过程

  1.3 Mbatis在哪写sql语句呢?如何设置sql参数和封装查询结果?

Mybatis 通过xml或注解的方式,讲要执行的各种statement 配置起来,并通过java对象和statement中的sql进行映射,生成最终的sql语句,最后由Mybatis执行sql语句并将结果映射返回

2.Mybatis原理

   2.1 JDBC编程的回顾

这里我新建一个工程直接写代码,数据库语句附上


SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `orders`
-- ----------------------------
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '下单用户id',
  `number` varchar(32) NOT NULL COMMENT '订单号',
  `createtime` datetime NOT NULL COMMENT '创建订单时间',
  `note` varchar(100) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of orders
-- ----------------------------
INSERT INTO `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `orders` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);

-- ----------------------------
-- Table structure for item
-- ----------------------------
DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL COMMENT '商品名称',
  `price` float(10,1) NOT NULL COMMENT '商品定价',
  `detail` text COMMENT '商品描述',
  `pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
  `createtime` datetime NOT NULL COMMENT '生产日期',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of item
-- ----------------------------
INSERT INTO `item` VALUES ('1', '台式机', '3000.0', '该电脑质量非常好!!!!', null, '2016-02-03 13:22:53');
INSERT INTO `item` VALUES ('2', '笔记本', '6000.0', '笔记本性能好,质量好!!!!!', null, '2015-02-09 13:22:57');
INSERT INTO `item` VALUES ('3', '背包', '200.0', '名牌背包,容量大质量好!!!!', null, '2015-02-06 13:23:02');

jdbc代码:

public class JdbcDemo {
public static void main(String[] args)  {
	 Connection connection=null;
	 PreparedStatement prepareStatement=null;
	 ResultSet rs =null;
	try {
		//1. 注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2. 获得数据库连接
		  connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/ssm"
				+ "?characterEncoding=utf-8", "root", "123456");
		  //3.定义查询
		  String sql ="select * from user where id = ? ";
		  //4.获取预处理statement
		  prepareStatement = connection.prepareStatement(sql);
		  //5.设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
		  prepareStatement.setInt(1, 1);
		  //6.发送sql获得结果集
		   rs = prepareStatement.executeQuery();
		  //7.遍历结果集
		 while(rs.next()){
			 System.out.println(rs.getString("username"));
		 }
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}finally{
		//8 释放资源
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(prepareStatement!=null){
			try {
				prepareStatement.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(connection!=null){
			try {
				connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
}
}

  2.2 Mybatis解决了哪些问题?

    1.  jdbc方式创建数据库连接相关的操作,存在硬编码(直接写在了代码里)。
      
        解决办法:通过Mybatis全局的配置文件,对数据库连接进行配置。
    
    2. statement相关操作存在硬编码(查询语句直接写在代码里)

        解决办法:通过Mapper映射文件,对statement相关处理进行配置
     
     3.频繁的开启数据库连接,会降低数据库处理性能。
        
         解决办法:通过Mybatis全局配置文件,配置连接池

  2.3Mybatis架构





1.加载配置(SqlSessionFactoryBuilder)

a) .SqlMapConfig.xml,此文件作为Mybatis的全局配置文件,配置了Mybatis的运行环境,

b).Mapper.xml 此文件作为Mybatis的sql映射文件,配置了操作数据库的sql语句,此文件需要在全局配置文件中加载。

2.通过加载配置信息构造SqlSessionFactory会话工厂

3.通过会话工厂创建SqlSession会话,我们通过操作SqlSession会话接口对数据库进行crud

4.Mybatis底层定义了Exexutor执行器来具体操作数据库,Executor 接口有两个实现类,一个是基本执行器(默认) 一个是缓存执行器,sqlSession底层是通过Executor接口操作数据库的。

5.Mapped Statement 也是Mybatis一个底层封装对象,它包装了Mybatis配置信息以及sql映射信息等,mapper.xml文件中一个select/insert/update/delete 标签对应一个 MappedStatement 对象,同时select/insert/update/delete 的id也是MappedStatement的id。

a)      MappedStatement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

b) Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

3.Mybatis入门程序

3.1 需求

1、根据用户id查询一个用户信息

2、根据用户名称模糊查询用户信息列表

3、添加/更新/删除用户


3.2 环境准备

 a). 导入Mybatis.jar包,我这里使用的3.2.7,导入mysql.jar,log4j.jar(非必须).......

 b). SqlMapConfig.xml,在classpath config下创建

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<!-- 和spring整合后 environments配置将废除-->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理-->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池,mybatis本身的连接池-->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	
</configuration>

SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。


 c).在classpath sqlmap下创建UserMapper.xml

 namespace 命名 空间,用于隔离sql,后面讲解另一个作用

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
</mapper>

 d). 将映射文件加载到主配置文件中

		<!-- 加载映射文件 -->
	<mappers>
		<mapper resource="sqlmap/UserMapper.xml"></mapper>

	</mappers>

 e).Po类作为mybatis进行sql映射使用,po类通常与数据库表对应,需求对应的PO类User.java如下:

public class User {
	private int id;
	private String username;// 用户姓名
	private String sex;// 性别
	private Date birthday;// 生日
	private String address;// 地址


get/set……

f). 根据id查询用户

<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="cn.nanjin.po.User">
select * from user where id =#{NanJin}
</select>
</mapper>

parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。

resultType:定义结果映射类型。因为是普通类型(java基本类型)的查询,所以#{里面写什么都行}



测试类:

public class MybatisTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void createSqlSessionFactory() throws Exception{
	// 配置文件
			String resource = "SqlMapConfig.xml";
			InputStream inputStream = Resources.getResourceAsStream(resource);
			// 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory
			sqlSessionFactory = new SqlSessionFactoryBuilder()
					.build(inputStream);

}
@Test
public void testFindUserById(){
	SqlSession sqlSession =null;
	try{
		//打开session
		sqlSession = sqlSessionFactory.openSession();
		User u = sqlSession.selectOne("test.findUserById",10);
		System.out.println(u);
	}catch (Exception e) {
		e.printStackTrace();
	}finally {
		if (sqlSession != null) {
			sqlSession.close();
		}

	}
}
}

2、根据用户名称模糊查询用户信息列表

public void testFindUserByUsername(){
	SqlSession sqlSession =null;
	try{
		//打开session
		sqlSession = sqlSessionFactory.openSession();
		 List<User> selectList = sqlSession.selectList("test.findUserByUserName","小");
		System.out.println(selectList);
	}catch (Exception e) {
		e.printStackTrace();
	}finally {
		if (sqlSession != null) {
			sqlSession.close();
		}

	}
}
<select id="findUserByUserName" parameterType="string" resultType="cn.nanjin.po.User">
<!-- resultType:结果映射的java类型,指的是单条结果对应的java类型 -->
	select * from user where username like '%${value}%'
	</select>

这里我们需要注意的是,我没有在使用#{} 而是使用了${value}

使用#{}完成的sql如下 

select * from user where username like '%'小'%'

使用${}时的sql如下

select * from user where username like '%小%'

可以知道${}是实现了sql的拼接,类似于普通的statement,而#{}则类似于prepareStatement,防止了注入危险。


小结:

1. #{}和${}

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。



${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,不过会引起SQL注入。 ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。


2. parameterType和resultType

parameterType:指定输入参数的java类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中


resultType:指定输出结果要映射的java类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。


3. selectOne和selectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)



selectList可以查询一条或多条记录。


3.新增用户,并返回新增用户id

这里说两种配置

mysql主键自增的返回
<insert id="insertUserone" parameterType="cn.nanjin.po.User">
<selectKey order="AFTER" resultType="int" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
	INSERT INTO user (username,birthday,sex,address) VALUES
		(#{username},#{birthday},#{sex},#{address});
</insert>
public void insertUserone(){
	SqlSession sqlSession =null;
	try{
		//打开session
		sqlSession = sqlSessionFactory.openSession();
		User u =new User();
		u.setAddress("heheh");
		u.setBirthday(new Date());
		u.setUsername("hifdenf");
		sqlSession.insert("test.insertUserone", u);
		System.out.println(u.getId());
		sqlSession.commit();
	}catch (Exception e) {
		e.printStackTrace();
	}finally {
		if (sqlSession != null) {
			sqlSession.close();
		}

	}

这里解释一下xml中的配置,<selectKey>查询主键,order属性取值为AFTER和BEFORE(必须大写否则报错)
注意一点,只有自增的主键order为AFTER,其余都用BEFORE

有时我们习惯用uuid,那我们应该这么写,

 	<insert id="insertUser" parameterType="cn.nanjin.po.User"> 
 		<selectKey order="BEFORE" keyProperty="id" resultType="string">
			SELECT UUID()
		</selectKey>

		INSERT INTO user (id,username,birthday,sex,address) VALUES
		(#{id},#{username},#{birthday},#{sex},#{address});
	</insert> 

4.更新id为10的用户

<update id="updateUser" parameterType="cn.nanjin.po.User">
UPDATE user set username=#{username},address=#{address} WHERE id =#{id}
</update>

	//打开session
		sqlSession = sqlSessionFactory.openSession();
		User u =new User();
		u.setAddress("NanJinilove");
		
		u.setUsername("NanJin");
		u.setId(10);
		sqlSession.update("test.updateUser", u);
		System.out.println(u.getId());
		sqlSession.commit();


5.删除的用户

<delete id="deleteUser" parameterType="int">
delete from user where id =#{id}
</delete>

增删改别忘了提交事物就Ok了~

4.Mybatis两种开发模式(接口和动态代理)


4.1 SqlSession 适用范围

SqlSession中封装了对数据库的操作,crud
SqlSession是通过SqlSessionFactory创建的,而SqlSessionFactory是由SqlSessionFactoryBuilder创建

4.1.1  SqlSessionFactory


SqlSessionFactory是一个接口,接口中定义了OpenSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用的运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory

4.1.2 SqlSession

SqlSession是一个面向用户的接口,SqlSession中定义了数据库的操作方法,每个线程都有自己的SqlSession实例,SqlSession的实例不能共享使用,它也是线程不安全的,因此最佳的范围应该是请求或者方法范围,绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
打开一个SqlSession使用完毕就要关闭,通常把关闭操作放到finally块中,确保每次都能执行关闭
SqlSession session = sqlSessionFactory.openSession();
	try {
 		 // do work
	} finally {
  		session.close();
	}

4.2 接口Dao,主要是为了历史遗留的ibatis,需要编写Dao接口和Dao实现类

public class UserDaoImpl implements UserDao {
	
	private SqlSessionFactory sqlSessionFactory;
	
	public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
		this. sqlSessionFactory = sqlSessionFactory;
	}

	@Override
	public User findUserById(int id ) {
		SqlSession session = sqlSessionFactory.openSession();
		
		
		return session.selectOne("test.findUserById", id);
	}

	@Override
	public List<User> findUsers(String name ) {
	
		SqlSession session = sqlSessionFactory.openSession();
		return session.selectList("test.findUserByUserName", name );
	}

}
@Test
public void selectUserDao(){
	UserDaoImpl userDao =new UserDaoImpl(sqlSessionFactory);
	User findUserById = userDao.findUserById(10);
	System.out.println(findUserById);
	
	List<User> findUsers = userDao.findUsers("小明");
	System.out.println(findUsers);
	}
}
<mapper namespace="test">
	<!-- 根据用户ID查询用户信息 -->
	<!-- select/insert/update/delete:对应一个MappedStatement对象 -->
	<!-- id:statement的id -->
	<!-- #{}:表示占位符?.#{}里面可以指定参数名称 ,如果参数值是简单类型的参数,那么参数名称可以任意 -->
	<!-- parameterType:参数类型(Java对象类型) -->
	<!-- resultType:结果映射类型(Java对象类型) -->
	<select id="findUserById" parameterType="int"
		resultType="cn.nanjin.po.User">
		SELECT * FROM user WHERE id = #{NanJin}
	</select>
	<select id="findUserByUserName" parameterType="string" resultType="cn.nanjin.po.User">
	select * from user where username like '%${value}%'
	</select>
	

4.2.1 接口方式存在的问题

1.Dao层存在重复代码,比如创建SqlSession
2.调用SqlSession的数据库操作方法需要指定statement的id,这里就存在硬编码问题,不利于维护

4.3 Mapper动态代理方式

4.3.1 开发规范

Mapper接口开发方式只需要我们编写Mapper接口(相当于Dao接口),由Mybaits框架根据接口定义创建接口的动态代理对象,代理对象的方法就是接口的实现类

规范:
1.Mapper接口的类路径与Mapper.xml中的namespace相同。
2.Mapper接口方法名称和Mapper.xml中定义的每个statement的id相同。
3.Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType类型相同。
4.Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType类型相同。

创建cn.nanjin.mapper包,config资源文件夹创建mapper资源目录

package cn.nanjin.mapper;

import java.util.List;

import cn.nanjin.po.User;

public interface UserMapper {
  User findUserById(int id );
  List<User> findUserByUserName(String name );
}

userMapper.xml
<mapper namespace="cn.nanjin.mapper.UserMapper">
	<!-- 根据用户ID查询用户信息 -->
	<!-- select/insert/update/delete:对应一个MappedStatement对象 -->
	<!-- id:statement的id -->
	<!-- #{}:表示占位符?.#{}里面可以指定参数名称 ,如果参数值是简单类型的参数,那么参数名称可以任意 -->
	<!-- parameterType:参数类型(Java对象类型) -->
	<!-- resultType:结果映射类型(Java对象类型) -->
	<select id="findUserById" parameterType="int"
		resultType="cn.nanjin.po.User">
		SELECT * FROM user WHERE id = #{NanJin}
	</select>
	<select id="findUserByUserName" parameterType="string" resultType="cn.nanjin.po.User">
	select * from user where username like '%${value}%'
	</select>
	</mapper>

test
@Test 
public void findUserByIdMapper(){
	SqlSession session = sqlSessionFactory.openSession();
         //获取代理对象
	UserMapper mapper = session.getMapper(UserMapper.class);
         //调用代理对象方法
	User user = mapper.findUserById(10);
	System.out.println(user);
	session.close();
}

4.3.2 小结

selectOne()和selectList

动态代理对象调用session.selectOne()或者session.selectList()是根据mapper接口方法的返回值决定的,如果返回list那么就调用selectLite,如果返回单个的对象就调用selectOne()

namespace

mybatis 官方推荐使用mapper代理的方法,我们不需要编写实现类

另外Mybaits的Mapper使用的是jdk的动态代理技术。

5.SqlMapConfig.xml配置文件

5.1配置文件中的内容和顺序

properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
       transactionManager(事务管理)
       dataSource(数据源)
mappers(映射器)

5.1.1  properties

a). 在classpath下定义db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
b). 在SqlMapConfig.xml中引用db.properties
   <properties resource="db.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.username}"/>
				<property name="password" value="${jdbc.password}"/>
			</dataSource>
		</environment>
	</environments>

当然也可以在properties中定义子标签
<properties>
<property name ="jdbc.username" value="nanjin"/>
</properties>

这里注意一点,Mybatis 按照读取properties内部元素属性---再读取resource或url加载的属性,会覆盖同名属性。

5.1.2 settings(全局配置参数)

<!-- 基本配置如下-->  
    <settings>  
        <!-- 该配置影响的所有映射器中配置的缓存的全局开关。默认值true -->  
      <setting name="cacheEnabled" value="true"/>  
      <!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认值false  -->  
      <setting name="lazyLoadingEnabled" value="true"/>  
        <!-- 是否允许单一语句返回多结果集(需要兼容驱动)。 默认值true -->  
      <setting name="multipleResultSetsEnabled" value="true"/>  
      <!-- 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。默认值true -->  
      <setting name="useColumnLabel" value="true"/>  
      <!-- 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 默认值false  -->  
      <setting name="useGeneratedKeys" value="false"/>  
     <!--  指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 -->   
     <!-- 默认值PARTIAL -->  
      <setting name="autoMappingBehavior" value="PARTIAL"/>  
        
      <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>  
     <!--  配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。默认SIMPLE  -->  
      <setting name="defaultExecutorType" value="SIMPLE"/>  
      <!-- 设置超时时间,它决定驱动等待数据库响应的秒数。 -->  
      <setting name="defaultStatementTimeout" value="25"/>  
        
      <setting name="defaultFetchSize" value="100"/>  
      <!-- 允许在嵌套语句中使用分页(RowBounds)默认值False -->  
      <setting name="safeRowBoundsEnabled" value="false"/>  
      <!-- 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。  默认false -->  
      <setting name="mapUnderscoreToCamelCase" value="false"/>  
      <!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。  
             默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。  
            若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。  -->  
      <setting name="localCacheScope" value="SESSION"/>  
      <!-- 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。  -->  
      <setting name="jdbcTypeForNull" value="OTHER"/>  
    <!--   指定哪个对象的方法触发一次延迟加载。  -->  
      <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>  
    </settings>  


5.1.3 typeAliases(别名)

别名

映射的类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

map

Map


自定义别名

<typeAliases>
	<!-- 单个别名定义 -->
	<typeAlias alias="user" type="cn.nanjin.po.User"/>
	<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
	<package name="cn.nanjin.po"/>
	
</typeAliases>

5.1.4 mappers(映射器)

	     <!-- resource是使用相对路径方式 -->
		<mapper resource="sqlmap/UserMapper.xml"></mapper>
		<mapper resource="mapper/UserMapper.xml"></mapper> 
		<!--使用mapper接口类路径,加载文件 -->
		<mapper class="cn.nanjin.mapper.UserMapper"/>
		<!-- 直接扫描包 -->
	    <package name="cn.nanjin.mapper"/>

注意:使用接口类路径/扫描包时,要求mapper接口名称和mapper映射文件名相同,并且放在同一目录

like this :



6.Mybatis与Hibernate不同

Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。


Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。


总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LawsonJin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值