mybatis的使用《一》

问题?mybatis的使用    Mybatis和hibernate的区别  EJB框架  mybatis环境搭建过程


一、EJB框架

(EJB重量级持久层,天然分布式,负载均衡)  但是不够灵活,不能充分适应业务。它实现的是多条件查询,如果使用EntityBean,做查询时,一种查询条件就得写一个sql。SessionBean新增,修改,删除交给EntityBean多条件查询交SessionBean,正是因为这个原因才导致了EJB框架的消亡


二、Mybatis定义

                 

MyBatis世界上流行最广泛的SQL 映射框架,由ClintonBegin在2002 年创建,iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。其后,捐献给了Apache基金会,成立了iBatis 项目。2010 年5 月,将代码库迁致Google Code,并更名为MyBatis


它和hibernate的概念差不多,都是基于JDBC开发的框架,不过它与hibernate最重要的一个区别是,它是基于jdbc轻量级的封装。


三、Mybatishibernate的区别(面试)

1.区别

            

Hibernate—>java面向对象盛行时期,将整个开发设计过程全部面向对象开发全ORM

iBatis,维持原有的编程方式,前面部分按面向对象思考和设计持久层时使用sql语句面向过程


1)  hibernate,将hql语句转为sqlSql无法优化",这方面在复杂大型项目,—>性能就不行了(针对中小型项目)

2)  Hibernate通过反射,性能很低

3)  Ibatis就是基于jdbc轻量级封装,还是使用sql。性能比较半OR


四、mybatis环境搭建过程


1.开发步骤



2.环境搭建(jar包)

jar包下载(包括核心包及依赖包)点击下载链接

mybatis-3.2.2.jar                        核心驱动

(以下为依赖包)

asm-3.3.1.jar

cglib-2.2.2.jar

commons-logging-1.1.1.jar

javassist-3.17.1-GA.jar

log4j-1.2.17.jar

slf4j-api-1.7.5.jar

slf4j-log4j12-1.7.5.jar

mysql-connector-java-5.1.26.jar     数据库驱动


3.搭建

(1).数据源配置 sqlMapConfig.xml配置文件文件(src下)

<span style="font-family:Microsoft YaHei;font-size:18px;"><?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>
	<!-- 简化 别名 ,别名在映射文件中用,可以起多个-->
	<typeAliases>
		<typeAlias type="com.itcast.domain.User" alias="Person"></typeAlias>
		<!-- <typeAlias type="" alias=""/> -->
	</typeAliases>
	
	<!-- 配置数据源,事务,当然最后整合的时候就交给spring了,default:采用哪种方式 -->
	<environments default="test">
	
		<!-- id:test/deploy  一种是测试的时候用,另外一种是发布的时候用 -->
		<environment id="test">
			<!-- 事务:JDBC/MANAGED-这是自己管理,后期就是给spring管理,这里使用JDBC管理 -->
			<transactionManager type="JDBC"></transactionManager>
			<!-- 数据源:POOLED/UNPOOLED/JNDI -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/mybatisEg1?charsetEncoding=utf8"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
		
		<environment id="deploy">
			<!-- 事务:JDBC/MANAGED-这是自己管理,后期就是给spring管理,这里使用JDBC管理 -->
			<transactionManager type="JDBC"></transactionManager>
			<!-- 数据源:POOLED/UNPOOLED/JNDI -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/mybatisEg1?charsetEncoding=utf8"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
		
	</environments>
	
	<!-- 映射文件mapper 这里和hibernate一样的,本文件就和hibernate.cfg.xml一样功能,MyBatis引用了hibernate的一些思想-->
	<mappers>
		<mapper resource="com/itcast/mapper/UserMapper.xml"/>
	</mappers>
</configuration></span>

记得要创建数据库,我新建的是MyBatisEg1,暂时不需要建表,先测试搭建成功没


(2).建测试类qlSessionFactoryBuilder.builer()创建一个SqlSessionFactory,看看是否搭建成功

<span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.test;
import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

public class TestMybatis {
	@Test
	public void init() throws IOException{
		String resource = "sqlMapConfig.xml";
		InputStream is = Resources.getResourceAsStream(resource);
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
		SqlSession session = factory.openSession();
	}
}
</span>

结果:

               

出现红色警告是因为缺少日志文件log4j,但是我们jar包导入了,只是缺少它的配置文件log4j.properties,将它放入src下(即是classpath下),再次运行就没有这个红色警告了。

如果想看具体的底层操作sql语句,可以将日志文件中的log4j.rootLogger=DEBUG,,修改成DEBUG模式,具体效果看下面:

               

(3).通过SqlSessionFactory获取SqlSession,可以调用CRUD操作

建表:

      

创建实体类,包括setget方法

<span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.domain;

import java.io.Serializable;

public class User implements Serializable {

	private Integer id;
	private String username;
	private String password;
	private Integer age;
	private String remark;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getRemark() {
		return remark;
	}
	public void setRemark(String remark) {
		this.remark = remark;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password="
				+ password + ", age=" + age + ", remark=" + remark + "]";
	}
	
	
	
	
	
}
</span>

(4).和hibernate文件一样对应的又映射文件UserMapper.xml(不一定要在同一个包下,可以放在另外一个包下,这个在sqlMapConfig.xml中配置路径了)

这个映射文件非常重要,跟以往的映射文件大不相同,与hibernate 的不同在这里也开始体现,因为它的数据库底层操作,写sql语句也在这个文件当中


<span style="font-family:Microsoft YaHei;font-size:18px;"><?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="com.itcast.mapper">
	<!-- SQL片段:无疑是用来替换SQL部分的 -->
	<sql id="sql1">id,username,password,age,remark</sql>
	<!-- 最强大的功能,resultMap 描述中间 对象属性和结果集中的对应关系 id取个名字-->
	<resultMap type="com.itcast.domain.User" id="UserRM">
		<!-- 主键  property:实体属性  column:结果集的字段名(没写,默认就是数据库列名) -->
		<id property="id" column="id"/>
		
		<!-- 普通字段 -->
		<result property="username" column="username"/>
		<result property="password" column="password"/>
		<result property="age" column="age"/>
		<result property="remark" column="remark"/>
		
		<!-- 关联关系 -->
	</resultMap>

	<!-- 查询 注意MyBatis中如果有些集合类型,只填写元素的类型 -->
	<!-- 可以随意取   resultType="List<User>" mybatis可以去猜类型,所以我们不需要这样写,直接写类 -->
	<!-- 可以写resultMap 值为之前配置好的resultMap的id值 -->
	<!-- 在这里和hibernate的映射文件就有很大的区别了 -->
	<!-- 执行结果,封装到对象结果集中,这个操作又底层操作完成 -->
	<select id="find" resultMap="UserRM">
		select * from user
	</select>
	
	
	<!-- 查询一个值 -->
	<select id="getid" parameterType="int" resultType="Person">
		select <include refid="sql1"/> from user
		where id = #{pid}
	</select>

	<!-- 带条件的查询  where 能自动去掉前面的and 或 or-->
	<select id="condition" resultMap="UserRM" parameterType="map">
		select * from user
		<where>
			<if test="username!=null">username like #{username}</if>
			<if test="age!=null"><![CDATA[and age<=]]>#{age}</if>
		</where>
		
		<!-- 特殊字符处理 <![CDATA[ ]]> 转化成文本内容处理-->
	</select>
	
	
	<!-- 增加一个  parameterType:传过来的自然就是一个实体了,而#{}这里面的值必须是实体类中的属性-->
	<insert id="insert" parameterType="com.itcast.domain.User">	
		insert into user 
		values
		(#{id},#{username},#{password},#{age},#{remark})
	</insert>
	
	
	<!-- 删除一个 -->
	<delete id="deleteOne" parameterType="int">
		delete from user where id=#{pid}
	</delete>
	
	
	<!-- 删除多条 -->
	<delete id="deleteMany" parameterType="int">
		delete from user 
		where id in
		<foreach collection="array" item="id" open="(" close=")" separator=",">
			#{id}
		</foreach>
	</delete>


	<!-- 更新 -->
	<update id="update" parameterType="com.itcast.domain.User">
		update user
		<!-- set id=#{id},username=#{username},password=#{password},age=#{age},remark=#{remark} -->
		<set>
			<if test="id!=null">id=#{id},</if>
			<if test="username!=null">username=#{username},</if>
			<if test="password!=null">password=#{password},</if>
			<if test="age!=null">age=#{age},</if>
			<if test="remark!=null">remark=#{remark}</if>
		</set>
		where id=#{id}
	</update>
	
	
	<!-- 获取记录条 -->
	<select id="count" resultType="int">
		select count(*) from user
	</select>
	
</mapper></span>


(5).建测试类

<span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.test;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import com.itcast.domain.User;
import com.itcast.util.MyBatisSqlSessionFactiorUtil;

public class sqlsessionFactoryTest extends MyBatisSqlSessionFactiorUtil{
//	private SqlSessionFactory factory;
	
	/*在MyBatis中,SqlSessionFactory线程上是安全的,所以可以抽取出来单独初始化。但是sqlsession不是安全的*/
	
//	@Before
//	public void test1() throws IOException{
//		String resource = "sqlMapConfig.xml";
//		InputStream inputStream = Resources.getResourceAsStream(resource);
//		 factory = new SqlSessionFactoryBuilder().build(inputStream);
//	}
	
	
	/*select ALL*/
	@Test
	public void selectAll() throws IOException{
		SqlSession session= factory.openSession();
		/*访问mapper中的方法  贵州:命名空间+id*/
		List<User> userlist = session.selectList("com.itcast.mapper.find");
		for(User user:userlist){
			System.out.println(user.toString());
		}
	}
	
	/*select one*/
	@Test
	public void selectUser(){
		SqlSession session = factory.openSession();
		/*session.selectOne(arg0, arg1):查询一条数据的方法 第一个参数命名空间+id  第二个参数则是传过去的值*/
		User user = session.selectOne("com.itcast.mapper.getid", 1);
		System.out.println(user.toString());
	}
	
	
	/*select 带条件查询  发现这样的效率想当低啊*/
	@Test
	public void selectUserCondtion(){
		SqlSession session = factory.openSession();
		/*session.selectOne(arg0, arg1):查询一条数据的方法 第一个参数命名空间+id  第二个参数则是传过去的值*/
		Map<String, Object> maplist = new HashMap<String, Object>();
		maplist.put("username", "li%");
		maplist.put("age", 21);
		List<User> userlist = session.selectList("com.itcast.mapper.condition", maplist);
		for(User user: userlist){
			System.out.println(user.toString());
		}
		
	}
	
	
	
	/*insert one*/
	@Test
	public void insetUser(){
		SqlSession session = factory.openSession();
		User user = new User();
		user.setId(6);
		user.setUsername("lijun1");
		user.setPassword("123456768");
		user.setAge(2);
		user.setRemark("sdsdsd");
		int i = session.insert("com.itcast.mapper.insert", user);
		if(i==1){
			System.out.println("成功插入!"+i);
		}else{
			System.out.println("不成功插入!"+i);
		}
		/*因为mybatis是轻量级的,默认是不提交事务的*/
		session.commit();
		System.out.println("已提交事务!");
	}
	
	/*Update one*/
	@Test
	public void updateUser(){
		SqlSession session= factory.openSession();
		User user = new User();
		user.setId(4);
		user.setUsername("李军1");
		user.setPassword("128");
		user.setAge(21);
		user.setRemark("Asdsdsd");
		int i=session.update("com.itcast.mapper.update", user);
		if(i==1){
			System.out.println("成功更新!"+i);
		}else{
			System.out.println("不成功更新!"+i);
		}
		/*因为mybatis是轻量级的,默认是不提交事务的*/
		session.commit();
		System.out.println("已提交事务!");
	}
	
	
	/*delete one*/
	@Test
	public void deleteOne(){
		SqlSession session = factory.openSession();
		int i =session.delete("com.itcast.mapper.deleteOne", 2);
		if(i==1){
			System.out.println("成功删除!"+i);
		}else{
			System.out.println("不成功删除!"+i);
		}
		/*因为mybatis是轻量级的,默认是不提交事务的*/
		session.commit();
		System.out.println("已提交事务!");
	}
	
	
	/*delete many(for method)*/
	@Test
	public void deleteMany(){
		SqlSession session = factory.openSession();
		int[] array1={5,6};
		int i = session.delete("com.itcast.mapper.deleteMany", array1);
		/*因为mybatis是轻量级的,默认是不提交事务的*/
		session.commit();
	}
	
	/*get count*/
	@Test
	public void getCount(){
		SqlSession session = factory.openSession();
		int i = session.selectOne("com.itcast.mapper.count");
		System.out.println("记录条有:"+i);
	}
	
	
}
</span>

因为SqlSessionFactory它是一个线程安全SqlSession它是线程不安全sqlSessionFactory在这里我们就可以抽取成工具类了。(工具类很好理解,就是在线程上保证安全,也是公共要使用的,抽出来共同使用即可)


参数注意:parameterMap废除,它是ibatis的。后来给google了,改为使用parameterType

获取动态参数:  ibatis:  #name# ibatis   mybatis: #{}, ${}   


注意selectOne时,结果集必须是一条记录,否则mybatis报错

org.apache.ibatis.exceptions.TooManyResultsException:Expected one result (or null) to be returned by selectOne(), but found: 3



(6).当数据库表字段和实体对象属性名称不一致时,怎么处理?
解决办法:
1) 通过sql的字段命名别名,别名跟实体对象属性一致,它就将相应的结果封装到set方法中了

select id,user_name as name,age,remark fromperson

Mybatis它对象映射是通过结果集的字段名称,在映射文件最开始的时候,配置实体类和数据库表的关联了。


2)  Mybatis最强大功能 resultMap对象(里面放实体类)

没写resultMap之前:

<span style="font-family:Microsoft YaHei;font-size:18px;"><?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="com.itcast.mapper">


	<!-- 查询 注意MyBatis中如果有些集合类型,只填写元素的类型 -->
	<!-- 可以随意取   resultType="List<User>" mybatis可以去猜类型,所以我们不需要这样写,直接写类 -->
	<!-- 在这里和hibernate的映射文件就有很大的区别了 -->
	<!-- 执行结果,封装到对象结果集中,这个操作又底层操作完成 -->
	<select id="find" resultType="com.itcast.domain.User">
		select * from user
	</select>
	<!-- 查询一个值 -->
	<select id="getid" parameterType="int" resultType="com.itcast.domain.User">
		select * from user
		where id = #{pid}
	</select>
</mapper>
</span>

ResultMap之后

<span style="font-family:Microsoft YaHei;font-size:18px;"><?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="com.itcast.mapper">

	<!-- 最强大的功能,resultMap 描述中间 对象属性和结果集中的对应关系 id取个名字-->
	<resultMap type="com.itcast.domain.User" id="UserRM">
		<!-- 主键  property:实体属性  column:结果集的字段名(没写,默认就是数据库列名) -->
		<id property="id" column="id"/>
		
		<!-- 普通字段 -->
		<result property="username" column="username"/>
		<result property="password" column="password"/>
		<result property="age" column="age"/>
		<result property="remark" column="remark"/>
		
		<!-- 关联关系 -->
	</resultMap>

	<!-- 查询 注意MyBatis中如果有些集合类型,只填写元素的类型 -->
	<!-- 可以随意取   resultType="List<User>" mybatis可以去猜类型,所以我们不需要这样写,直接写类 -->
	<!-- 可以写resultMap 值为之前配置好的resultMap的id值 -->
	<!-- 在这里和hibernate的映射文件就有很大的区别了 -->
	<!-- 执行结果,封装到对象结果集中,这个操作又底层操作完成 -->
	<select id="find" resultMap="UserRM">
		select * from user
	</select>
	<!-- 查询一个值 -->
	<select id="getid" parameterType="int" resultMap="UserRM">
		select * from user
		where id = #{pid}
	</select>
</mapper>
</span>


(7).结果集

resultType       基础类型,int,string,Person

resultMap       针对resultMap标签(使用这个,一定要写resultMap配置)


(8).删除多个值

因为上面案例,我只写了整形数组删除多条,还有其他方法


Lsit方式删除

<span style="font-family:Microsoft YaHei;font-size:18px;">	<!-- 删除多条,LIST集合 -->
	<delete id="deleteList" parameterType="int">
		delete from person
		where id in
		<foreach collection="list" item="id" open="(" close=")" separator=",">
			#{id}
		</foreach>
	</delete>
</span>

test

<span style="font-family:Microsoft YaHei;font-size:18px;">public void testDeleteByList(){
		SqlSession session = factory.openSession();
		List<Integer> _list = new ArrayList<Integer>();
		_list.add(4);
		_list.add(6);
		
		session.delete("cn.itcast.mapper.PersonMapper.deleteList", _list);
		session.commit();
	}
</span>

Map方式删除

<span style="font-family:Microsoft YaHei;font-size:18px;"><delete id="deleteMap" parameterType="int">
		delete from person
		where id in
		<foreach collection="map" item="id" open="(" close=")" separator=",">
			#{id}
		</foreach>		
	</delete>
</span>

test

<span style="font-family:Microsoft YaHei;font-size:18px;"><span style="font-family:Microsoft YaHei;">	@Test	//删除多条 MAP
	public void testDeleteByMap(){
		SqlSession session = factory.openSession();
		Map<Integer,Object> paraMap = new HashMap<Integer,Object>();
		paraMap.put("ids", 1);
		paraMap.put("ids", 2);
		session.delete("cn.itcast.mapper.PersonMapper.deleteMap", paraMap);
		session.commit();
	}
</span></span>


删除多条,Map , ids 代表map中key

<span style="font-family:Microsoft YaHei;font-size:18px;"><delete id="deleteMap" parameterType="map">
		delete from person
		where id in
		<foreach collection="ids" item="id" open="(" close=")" separator=",">
			#{id}
		</foreach>		
	</delete>
</span>

test

<span style="font-family:Microsoft YaHei;font-size:18px;">@Test	//删除多条 MAP
	public void testDeleteByMap(){
		SqlSession session = factory.openSession();
		Map<String,Object> paraMap = new HashMap<String,Object>();
		int[] ids = {4,6};
		paraMap.put("ids", ids);
		
		session.delete("cn.itcast.mapper.PersonMapper.deleteMap", paraMap);
		session.commit();
	}
</span>

(8).实体类别名

在配置文件sqlMapConfig.xml中增加别名

<span style="font-family:Microsoft YaHei;font-size:18px;"><!-- 起别名 -->
	<typeAliases>
		<typeAlias type="cn.itcast.domain.Person" alias="Person"/>
	</typeAliases>
</span>

在UserMapper.xml(映射文件)中使用

<span style="font-family:Microsoft YaHei;font-size:18px;"><!-- 查询一个,按id查询 -->
	<select id="get" parameterType="int" resultType="Person">
		select * from person
		where id = #{pid}
	</select>
</span>


(9).SQL片段

在映射文件中

<span style="font-family:Microsoft YaHei;font-size:18px;"><sql id="cols">id,user_name,age,remark</sql>

	<select id="find" resultMap="personRM">
		select <include refid="cols"/> from person
	</select>
</span>

传参:map和po对象实体,查询条件封装

例如:年龄(整数),出生日期,入职日期(日期)

日期,有开始时间,结束时间

Map随意构造


(10).动态SQL语句的使用

a)<where> 能自动去掉where最前面and或者or

<span style="font-family:Microsoft YaHei;font-size:18px;">	<select id="find" parameterType="map" resultMap="personRM">
		select <include refid="cols"/> from person
		<where>
		<if test="name!=null">and user_name like #{name}</if>
		<if test="age!=null">and age=#{age}</if>
		</where>
	</select>
</span>

(10).<set>自动删除最后一个逗号

<span style="font-family:Microsoft YaHei;font-size:18px;"><set>
			<if test="name!=null">user_name=#{name},</if>
			<if test="age!=null">age=#{age},</if>
			<if test="remark!=null">remark=#{remark},</if>
		</set>
</span>

(11).遍历

<span style="font-family:Microsoft YaHei;font-size:18px;">	<foreach collection="ids" item="id" open="(" close=")" separator=",">
			#{id}
		</foreach>	

		where id in
		(
		<foreach collection="array" item="id" separator=",">
			#{id}	
		</foreach>
		)
</span>

(12).特殊符号的处理

特殊字符处理 <![CDATA[ ]]> 转化成文本内容处理

<span style="font-family:Microsoft YaHei;font-size:18px;"><where>
			<if test="username!=null">username like #{username}</if>
			<if test="age!=null"><![CDATA[and age<=]]>#{age}</if>
		</where></span>

像在这里“<”这个就无法识别


五、对象关联关系

1.一对一关联

说的首先得明白,hibernate中的一对的关联关系是在映射文件中注明的,在这点上和mybatis有很大的区别mybatis中不需要这样注明两者之间的一对一关联,只需要是sql语句中,同时查询出来即可。


老规矩,首先MyBatis的配置文件sqlMapConfig.xml

<?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>
	<!-- 简化 别名 ,别名在映射文件中用,可以起多个-->
	<typeAliases>
		<typeAlias type="com.itcast.domain.User" alias="Person"></typeAlias>
		<!-- <typeAlias type="" alias=""/> -->
	</typeAliases>
	
	<!-- 配置数据源,事务,当然最后整合的时候就交给spring了,default:采用哪种方式 -->
	<environments default="test">
	
		<!-- id:test/deploy  一种是测试的时候用,另外一种是发布的时候用 -->
		<environment id="test">
			<!-- 事务:JDBC/MANAGED-这是自己管理,后期就是给spring管理,这里使用JDBC管理 -->
			<transactionManager type="JDBC"></transactionManager>
			<!-- 数据源:POOLED/UNPOOLED/JNDI -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/mybatisEg1?charsetEncoding=utf8"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
		
		<environment id="deploy">
			<!-- 事务:JDBC/MANAGED-这是自己管理,后期就是给spring管理,这里使用JDBC管理 -->
			<transactionManager type="JDBC"></transactionManager>
			<!-- 数据源:POOLED/UNPOOLED/JNDI -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/mybatisEg1?charsetEncoding=utf8"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
		
	</environments>
	
	<!-- 映射文件mapper 这里和hibernate一样的,本文件就和hibernate.cfg.xml一样功能,MyBatis引用了hibernate的一些思想-->
	<mappers>
		<mapper resource="com/itcast/mapper/UserMapper.xml"/>
		<mapper resource="com/itcast/mapper/UserInfMapper.xml"/>
	</mappers>
</configuration>

扩展拓展用户信息职业,新建另外一个对一的表:user_inf(id和user中的id对应)



信息自己添加,查询一下:

     

遇到这种id相同,到时候mybatis无法识别,然后存贮在实体类的时候,会出现问题,怎么处理?

很简单,在查询的时候,赋  别名


此一对一的例子,是在原来的基础上做的 UserMapper.xml文件依然不变。但是User实体类需要做点儿改变

定义

private User_inf user_inf;//一对一的体现,并且setget方法。


添加User_inf实体类:

package com.itcast.domain;

import java.io.Serializable;
import java.util.Date;

public class User_inf implements Serializable{
	private Integer id;
	private String inf;
	private Date time;
	
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getInf() {
		return inf;
	}
	public void setInf(String inf) {
		this.inf = inf;
	}
	public Date getTime() {
		return time;
	}
	public void setTime(Date time) {
		this.time = time;
	}
	@Override
	public String toString() {
		return "User_inf [id=" + id + ", inf=" + inf + ", time=" + time + "]";
	}
	
	
	
}

添加映射配置文件UserInfMapper.xml

配置resultMap第一种方式:(不常用,而且不好变通)

<!-- 最强大的功能,resultMap 描述中间 对象属性和结果集中的对应关系 id取个名字-->
	<resultMap type="com.itcast.domain.User" id="UserRM">
		<!-- 主键  property:实体属性  column:结果集的字段名(没写,默认就是数据库列名) -->
		<id property="id" column="id"/>
		
		<!-- 普通字段 -->
		<result property="username" column="username"/>
		<result property="password" column="password"/>
		<result property="age" column="age"/>
		<result property="remark" column="remark"/>
		
		<!-- 关联关系  和hibernate的映射文件关联有很大的区别-->
		<!-- 一对一  javaType:只有在对一的时候采用-->
		<association property="user_inf" javaType="com.itcast.domain.User_inf">
			<id property="id" column="id"/>
			<result property="inf" column="inf"/>
			<result property="time" column="time"/>
		</association>
	</resultMap>


配置resultMap第二种方式:(运用继承的方式常用,好变通)

<?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="com.itcast.mapper.userinfMapper">
<!-- 较UserMapper.xml文件的配置一样,一样是关联在一起的  不过更加灵活了,需要谁就使用谁-->
	<resultMap type="com.itcast.domain.User" id="userInfRm1">
		<id property="id" column="id"/>
		<result property="username" column="username"/>
		<result property="password" column="password"/>
		<result property="age" column="age"/>
		<result property="remark" column="remark"/>
	</resultMap>
	
	<!--  一对一的那个,不想影响实体的话,就使用继承的方式:  对一使用 association 所对应使用的是javaType  -->
	<resultMap type="com.itcast.domain.User" id="userInfRm2" extends="userInfRm1">
		<association property="user_inf" javaType="com.itcast.domain.User_inf">
			<id property="id" column="id"/>
			<result property="inf" column="inf"/>
			<result property="time" column="time"/>
		</association>
	</resultMap>


	<!-- 查询User及User_inf表中的一一对应关系 -->
	<select id="findUserAndInf" parameterType="map" resultMap="userInfRm2">
		select p.id,p.username,p.password,p.age,p.remark,
		i.id as infid,i.inf,i.time from
		(select id,username,password,age,remark from user) p
		left join (select id,inf,time from user_inf) i on p.id=i.id
		<where>
			<if test="name!=null">username=#{name}</if>
		</where>
	</select>
	

</mapper>

建立测试类:UserInfTest

package com.itcast.test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import com.itcast.domain.User;
import com.itcast.util.MyBatisSqlSessionFactiorUtil;

public class UserInfTest extends MyBatisSqlSessionFactiorUtil{
	
	@Test
	public void test1(){
		SqlSession session =factory.openSession();
		Map map1 = new HashMap();
		map1.put("name", "lijun");
		List<User> list = session.selectList("com.itcast.mapper.userinfMapper.findUserAndInf", map1);
		for(User user:list){
			System.out.println(user.toString()+"\n"+user.getUser_inf().toString());
		}
	}
}

结果:

     


错误:原因是因为,映射文件没有加入到配置文件中

          


2.一对多的关联 

一对的对,记住一个就对多的概念,只需要负责对多的那边。hibernate中对多一半用set集合,而mybatis一般用list集合。

建一个Book表,表示一本书可以让多个人拥有。

   


修改User实体类:加对多  private List<Book> books;//一对多的体现  并且setget方法

添加Book实体类:

package com.itcast.domain;

import java.io.Serializable;

public class Book implements Serializable{
	
	private Integer id;
	private String book_name;
	private Double book_money;
	//不配双向关联的
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getBook_name() {
		return book_name;
	}
	public void setBook_name(String book_name) {
		this.book_name = book_name;
	}
	
	public Double getBook_money() {
		return book_money;
	}
	public void setBook_money(Double book_money) {
		this.book_money = book_money;
	}
	@Override
	public String toString() {
		return "Book [id=" + id + ", book_name=" + book_name + ", book_money="
				+ book_money + "]";
	}
	
	
	
	
}

映射文件直接可以在 UserInfMapper.xml中添加

<?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="com.itcast.mapper.userinfMapper">
<!-- 较UserMapper.xml文件的配置一样,一样是关联在一起的  不过更加灵活了,需要谁就使用谁-->
	<resultMap type="com.itcast.domain.User" id="userInfRm1">
		<id property="id" column="id"/>
		<result property="username" column="username"/>
		<result property="password" column="password"/>
		<result property="age" column="age"/>
		<result property="remark" column="remark"/>
	</resultMap>
	
	<!--  一对一的那个,不想影响实体的话,就使用继承的方式:  对一使用 association 所对应使用的是javaType  -->
	<resultMap type="com.itcast.domain.User" id="userInfRm2" extends="userInfRm1">
		<association property="user_inf" javaType="com.itcast.domain.User_inf">
			<id property="id" column="id"/>
			<result property="inf" column="inf"/>
			<result property="time" column="time"/>
		</association>
	</resultMap>
	
	<!-- 一对多的那个,不想影响实体的话,就使用继承的方式   :   对多使用:collection,所对应使用的是ofType(一完之前涉及到一对一,如果需求里面只要一对多,就继承主的那个,如果两个都需要,就继承第二个)-->
	<resultMap type="com.itcast.domain.User" id="userBookRm" extends="userInfRm2">
		<collection property="books" ofType="com.itcast.domain.Book">
			<id property="id" column="id"/>
			<result property="book_name" column="book_name"/>
			<result property="book_money" column="book_money"/>
		</collection>
	</resultMap>
	
	
	
	
	
	
	<!-- 查询User及User_inf表中的一一对应关系 -->
	<select id="findUserAndInf" parameterType="map" resultMap="userInfRm2">
		select p.id,p.username,p.password,p.age,p.remark,
		i.id as infid,i.inf,i.time from
		(select id,username,password,age,remark from user) p
		left join (select id,inf,time from user_inf) i on p.id=i.id
		<where>
			<if test="name!=null">username=#{name}</if>
		</where>
	</select>
	
	
	<!-- 查询User及User_inf表中的一一对应关系及User到book的一对多:有条件的一条数据 -->
	<select id="Book" parameterType="map" resultMap="userBookRm">
		select 
		p.id,p.username,p.password,p.age,p.remark,p.infid,p.inf,p.time,b.bookid,b.book_name,b.book_money 
		from 
		(
		   select p.id,p.username,p.password,p.age,p.remark,i.infid,i.inf,i.time from
				(select id,username,password,age,remark from user) p
			    left join
				(select id as infid,inf,time from user_inf) i on p.id=i.infid
		)p
		left join(select id as bookid,book_name,book_money,userid from book) b
		on p.id=b.userid
		<where>
			<if test="name!=null">username=#{name}</if>
		</where>
	</select>
	
</mapper>

在这个映射文件中可以看出采用继承的方式的好处,到时候可以想用那个就可以用那个 resultMap,很方便,比上面一种直接全部属性卸载一个 resultMap变通很多


测试类:UserBookTest.java

package com.itcast.test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import com.itcast.domain.User;
import com.itcast.util.MyBatisSqlSessionFactiorUtil;

public class UserBookTest extends MyBatisSqlSessionFactiorUtil{
	@Test
	public void bookTest(){
		SqlSession session = factory.openSession();
		Map map1 = new HashMap();
		map1.put("name", "lijun");
		List<User> users = session.selectList("com.itcast.mapper.userinfMapper.Book",map1);
		for(User user:users){
			System.out.println("User信息:"+user.toString()+"\n Inf信息:"+user.getUser_inf().toString()+"\n Book信息:"+user.getBooks().toString());
		}
		System.out.println(users.size());
	}

}

结果:

   


六、SQL优化的问题

前面说过hibernate的JDBC底层封装,就注定了无法优化HQL语句的性能,但是MyBatis的sql语句是轻量级的封装依然保持着写SQL语句的习惯,这就意味着想优化系统的性能,可以在Sql语句上去优化


七、视图的问题

在做大型项目,视图可能废除。项目组不允许在项目中使用视图


八、总结

还没完呢?继续下一篇文章看看MyBatis的插件自动生成实体类和映射文件的方法吧查看博客文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值
>