一篇文章入门MyBatis3

要使用mybatis,需要在类路径下建立一个配置文件,名称为mybatis-config.xml

mybatis中的总配置文件(mybatis-config.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>

<!-- environments在集成Spring后不用配置,environment 元素体中包含了事务管理和连接池的配置 -->
	<!--environments 的id可以随意配置-->	
	<environments default="development">
		<environment id="development">
			<!-- 配置使用JDBC的事务,决定事务作用域和控制方式的事务管理器 -->
			<transactionManager type="JDBC" />
			<!-- 使用连接池 连接数据库 -->
			<dataSource type="POOLED">
				<!--连接数据库必要属性-->
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost/ssm_mybatis" />
				<property name="username" value="root" />
				<property name="password" value="123456789" />
				
			</dataSource>
		</environment>
	</environments>
	
	<!--用来关联实体类,xml对应一个类-->
	<mappers>
		<mapper resource="mapper/UserMapper.xml" />
	</mappers>
</configuration>

mybatis中的Mapper.xml:

mybatis通过实体类访问数据库,实体类要符合JavaBean规范
实体类要对应一个mapper.xml,名称随意,最好是类名 + Mapper.xml
如下(UserMapper.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:便于管理,相当于给mapper起个名字
  	在mapper内部是写sql语句的	
  -->
<mapper namespace="UserMapper">
	<!--select属性:
	id:给sql语句命名,用来调用
	parameterType:传入参数的类型(可选)
	resultType:返回值的类型(类路径),即使有多个返回值,不用写list类
	-->
	<select id="selectUserById" parameterType="Integer" resultType="model.User">
		<!--sql语句和原生的几乎一样,占位符不再是?,而是#{},而且需要取名字,名字没有要求-->
		select * from user where u_id = #{id}
	</select>
</mapper>

mybatisAPI以及基本查询:

在类中使用mybatisAPI使用mybatis操作数据库:

		//将mybatis的配置文件路径保存为String,在类路径下可以直接保存名称
		String resource = "mybatis-config.xml";
		
		//使用mybatis提供Resources读取配置文件,获取一个输入流
		InputStream inputStream = Resources.getResourceAsStream(resource);
		
		//新建一个mybatis提供的sqlSessionFactoryBuilder
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		
		//利用创建的builder读取输入流的数据创建SessionFactory
		SqlSessionFactory factory = builder.build(inputStream);
		
		//利用工厂打开一个sqlSession
		SqlSession session = factory.openSession();
		
		//操作数据库
		
//		参数1:要操作的SQL语句名称,在实体类的mapper文件里配置名称,命名空间 + id
//		参数2:sql语句的传入参数
//		查询一条数据,通过id = 1
		User user = (User)session.selectOne("UserMapper.selectUserById", 1);
		


//		如果进行增删改操作,则需要提交事务
//		session.commit();

mybatis其他数据库操作方式:

模糊查询:

///xml配置
//模糊查询不能使用#{},需要使用${},名称必须为value,${}为ognl表达式,可以用来字符串拼接
//如有需要,注意查询前设置数据库编码为utf8,否则无法显示中文数据
<select id="selectUserByName" parameterType="String" resultType="model.User">
		select * from user where u_id like '%${value}%'
</select>

//java语句
//如果查询结果为多个,可以用selectList
List<User> list = session.selectList("UserMapper.selectUserByName", "王");

插入数据:

//xml配置
<insert id="insertUser" parameterType="model.User">
	//使用#{}可以获取user实例中的字段,用法类似ognl表达式
	insert into user values(null, #{u_username},#{u_password},#{u_sex},#{u_createTime},#{u_cid});
</insert>

//java代码
User user = new User("A","B","C",new Date(),1);//创建测试实例
session.insert("insertUser", user);
session.commit();

修改数据

//xml配置
<update id="updateUserName" parameterType="model.User">
	update user set u_username = #{u_username} where u_id = #{u_id};
</update>

//java代码
User user = new User();
user.setU_id(1);//mybatis根据数据的id修改数据
session.update("updateUserName", user);
session.commit();

删除数据

//xml配置
<delete id="deleteUser" parameterType="Integer">
	delete from user where u_id = #{id};
</delete>
//java代码
session.delete("deleteUser", 1);
session.commit();	

创建MybatisUtils(获取session):

package utils;

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;

public class MybatisUtils {
	
	private static SqlSessionFactory sessionFactory = null;
	private static InputStream inputStream = null;
	
	static {
		String resource = "mybatis-config.xml";
		
		try {
			inputStream = Resources.getResourceAsStream(resource);
		} catch (IOException e) {
			e.printStackTrace();
		}
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		sessionFactory = builder.build(inputStream);
	}
	
	public static SqlSession getSession(){
		return sessionFactory.openSession();
	}
	
}	

mybatis动态代理(官方推荐):

使用一个可以和mapper.xml文件映射的接口实现动态代理
通过接口可mapper实现Dao的功能,而不是自己写Dao的实现类
UserMapper.xml

<mapper namespace="dao.UserMapper">
	<select id="selectUserById" parameterType="Integer"
		resultType="model.User">
		select * from user where u_id = #{id};
	</select>
</mapper>

UserMapper.java

public interface UserMapper {
	
	//mapper动态代理开发四大原则
	//1.接口方法名需要与mapper.xml的要调用的sql语句的id一致
	//2.接口的形参类型需要与mapper.xml parameterType一致
	//3.接口的返回值需要与mapper.xml resultType一致
	//4.mapper.xml中namespace要与接口的全包名一致
	
	public User selectUserById(Integer id);
	
}

动态方法调用:

//先使用getMapper获取接口实例(接口实例由mybatis根据mapper帮助实现)
UserMapper mapper = session.getMapper(UserMapper.class);

//然后就可以直接调用方法
User user = mapper.selectUserById(1);

在mybatis中使用log输出日志:

在项目目录下添加log4j.properties文件:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

%{}和#{}的区别:

#{}是占位符,运行时替换为‘参数’,带有单引号
%{}时ognl表达式,可以用作字符串拼接,传入参数不会添加单引号

mybatis中的properties属性:

properties(读取配置文件)
mybatis可以读取properties文件中的数据:

<properties resource="db.properties"/>

然后可以使用${}读取properties文件内容
通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

mybatis中的typeAliases(类型别名):

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

推荐使用包的形式设置别名,如果Javabean的数量比较多的话,使用包的形式设置别名,包下的所有类使用只要使用类名即可
报的形式会扫描主包及自包下的所有文件,以对象类名为别名,大小写不限,推荐使用小写

<typeAliases>
	<package name="model" />
</typeAliases>

mybatis中的mappers(配置映射器的位置):

mappers时写sql语句的地方
mappers可以使用绝对路径(url),相对路径(resource)、类名(class)、映射器
(name)定位,但由于都是单个配置,如果类多起来,比较麻烦,所以推荐使用包来配置:

<mappers>
	<package name="mapper"/>
</mappers>

使用包配置时,主要要将接口(动态调用)和xml文件都放在此包下

mybatis中的输入输出映射:

mybatis中的输入映射:
parameterType:可以是基本数据类,包装类(不仅仅时Integer、Double,还可以时List< User >,或者是自定义的包装类),自定义类,

mybaits中的输出映射:
可以这样理解:
mybatis从数据库中查找数据,查出的数据是一张表,第一行是各个属性名称,以下每一行都是一条记录,每条记录都可以转化为一个对象,那么如何转化为对象?设置resultType提供一个类名,让mybatis自己判断如何构造对象:
resultType:
首先根据提供的类构造一个对象,然后再逐一扫描result表每一行记录,每条记录从左到右扫描,如果如果扫描位置有值,如果bean类中有对应名称的setter方法,则用setter方法设置到对象中,否则跳过。
resultMap: 如果指定的是resultMap,则在每个记录注意扫描时去resultMap中检查是否存在该名称的映射,如果有,则按照设置的映射关系映射,如果没有则按照resultType的规则映射。

resultType和resultMap不能共用,只能用其中的一个

什么时候使用哪个?
resultType(自动映射,如果是实体类,需要实体类中的属性和数据库中的表完全一致才可以使用):可以是基本类型、自定义对象或是集合
resultMap(手动映射,实体类中的属性可以不和数据库中的列完全一致命名):bean中的属性值和数据库中的列不匹配
手动映射(例子):

<!---->
<!--resultMap属性:
	type:类型,就是映射bean类
	id:由于resultMap单独设置在查询标签外,所以需要用id来找到该resultMap标签
	result:可以理解为键值对映射
		-property:bean类中和数据库列名不一致的但对应的那个属性
		-column:数据库中和bean属性不一致但是对应的那一类
-->
<resultMap type="Country" id="country">
	<result property="id" column="c_id"/>
</resultMap>

<!--然后使用select标签时设置resultMap属性为上述id,就可以了-->
<select id="selectAll" resultMap="country">
	select * from country;
</select>
<!--没有设置的属性则会自动映射(需要属性名和数据库列名一致)-->

mybatis的关联查询:

在mybatis中设置关联的作用(个人理解):
其实使用sql进行多表查询已经不是问题,使用各种连接,只要有数据,都不是问题。问题是如何把这些数据封装成一个个对象方便操作呢?我们需要一个能够能承载查询信息的类,毫无疑问就是实体类,怎样把数据放到实体类中?这里需要使用resultMap(mybatis多表查询不能用resultType)
假如有一个用户类和一个国家类,则一个用户对一个国家,一个国家对多个用户。

示例:
一个用户对一个国家(一对一):

<!---->

<resultMap type="User" id="userinfo">
	<!--使用多表查询时,只有手动配置的属性才会被查询,没有手动配置的属性不会获取-->
	<!--使用id标识主键,使用result标识普通属性,可以混用,但是最好区别开-->
	<id property="u_id" column="u_id" />
	<result property="u_username" column="u_username" />
	<result property="u_sex" column="u_sex" />
	<result property="u_cid" column="u_cid" />

<!--association用来接收一对一的另一个表的信息(国安):
	property:接受类中另一个类的引用名称
	javaType:另一个类的类型
	
	-->
	<association property="country" javaType="Country">
		<result property="c_countryname" column="c_countryname"/>
		<result property="c_capital" column="c_capital"/>
	</association>

</resultMap>
<select id="selectUserInfoOnetoOne" 
	resultMap="userinfo">
	select
	u_id,u_username,u_sex,u_cid,c_countryname,c_capital
	from user u
	left join
	country c
	on
	u.`u_id` = c.`c_id`;
</select>

(一个国家对多个用户)一对多:

<!---->
<resultMap type="Country" id="countryuser">
	<id property="c_id" column="c_id" />
	<id property="c_countryname" column="c_countryname" />
	<id property="c_capital" column="c_capital" />

<!--collection 属性:
	property:接受类中的另一个类的集合引用
	ofType:集合类范型类型
	
-->
	<collection property="userLists" ofType="User">
		<result property="u_username" column="u_username"/>
		<result property="u_sex" column="u_sex"/>
	</collection>
</resultMap>
<select id="selectCountryUserManytoOne" resultMap="countryuser">
	select
	c_id,c_countryname,c_capital,u_username,u_sex
	from
	country c
	left join
	user u
	on
	u.`u_cid` = c.`c_id`;
</select>

mybatis动态sql:方便拼接sql语句

if标签:
在mybatis的sql语句中,可以使用if标签根据参数是否存在执行不同的sql语句:

<!---->
<select id="selectUserUseIf" resultType="User" parameterType="User">
	select u_id,
	<!--test后面跟上条件,获取传入的值不需要加上#{}-->
	<if test="u_username!=null">
		u_username,
	</if>
	u_sex from user;
</select>

但是拼接的sql语句中有and关键字时容易出现问题:

<!---->
<!--如果u_sex== null,sql语句and就会直接连接在where后面,着显然是错的-->
<select id="selectUserUseIf" resultType="User" parameterType="User">
	select * from user where
	<if test="u_sex!=null and u_sex!=''">
	u_sex = #{u_sex}
	</if>
	<if test="u_cid!=null">
	and u_cid = #{u_cid}
	</if>
</select>

mybatis提供了where标签解决这个问题,如果子句的开头是and,where会把它去掉,where标签默认前缀会生成where关键字
where标签:
解决if标签拼接字符串and符号问题

<select id="selectUserUseIf" resultType="User"
	parameterType="User">	
		select * from user
		<where>
		<if test="u_sex!=null and u_sex!=''">
			u_sex = #{u_sex}
		</if>
		<if test="u_cid!=null">
			AND u_cid = #{u_cid}
		</if>
	</where>
</select>

trim标签:
可以定制where标签的规则:

<!--示例-->
<!--
prefix:可以在运行时替换<trim>为a
suffix:可以在运行时替换</trim>为b
prefixOverrides:如果子句前缀为c,可以在必要时自动去除,可以使用 | 分隔多个选项
suffixOverrides:如果子句后缀为c,可以在必要时自动去除,可以使用 | 分隔多个选项
-->
<trim prefix="a" suffix="b" prefixOverrides="c" suffixOverrides="d">
</trim>

set标签:
解决拼接字符串时逗号问题
set标签用来替代手写的set关键字,可以在必要时去掉子句末尾的逗号,用法和where标签类似。

foreach标签:
如果sql使用in,可以用该标签动态生成数组:

<!---->
<select id="selectUserUserIn" resultType="User">
	select * from user u where u.`u_id` in 
	<!--如果传入的是List类型,则collection的值为list,如果是数组类型,则为array,如果时包装类,直接写引用名称-->
	<!--foreach属性:
		item:数组或集合的迭代值
		separator:每两个迭代值中的分隔符
		open:迭代开始时插入符号
		close:迭代结束时插入符号
	-->
	<foreach collection="array" item="num" separator="," open="(" close=")">
		#{num}
	</foreach>
</select>

sql标签:
可以提取重复sql重用:

<!---->
<!--设置sql语句-->
<sql id="selectuser">
	select * from user u 
</sql>
<!--使用-->
<include refid="selectuser"></include>

mybatis中的Generator(MBG)

作用:根据数据库表自动自动生成Bean对象,java接口及SqlMapper.xml配置文件:
Generator的配置
generatorConfig.xml):
放在src目录下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<!--  -->
	<!-- context为主要配置标签, targetRuntime为运行环境 -->
	<context id="MyGenerator" targetRuntime="MyBatis3">


		<!-- 可以让生成的代码简洁一点 -->
		<commentGenerator>
			<!-- 去掉注释 -->
			<property name="suppressAllComments" value="true" />
			<!-- 去掉时间戳 -->
			<property name="suppressDate" value="true" />

		</commentGenerator>


		<!-- 数据库连接信息,配置连接数据库的必要信息 -->
		<jdbcConnection 
			driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost/ssm_mybatis"
			userId="root"
			password="123456789">
		</jdbcConnection>

		<!-- javajdbc数据类型转换规则 ,设置为false则使用默认配置-->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- javaModelGenerator:javabean配置 
		targetPackage:输出包名 
		targetProject:输出项目位置 -->
		<javaModelGenerator targetPackage="com.echo.bean"
			targetProject="src">
			
			<!--enableSubPackages:是否开启子包名称 是否在包名后面架上scheme名称 -->
			<property name="enableSubPackages" value="false" />
			
			<!-- 在setter方法中加入trim,去掉空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>

		<!-- mapper.xml配置,属性作用同上-->
		<sqlMapGenerator targetPackage="com.echo.mapper"
			targetProject="src">
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>


		<!-- java接口的配置,属性作用同上,type设置生成的文件类型为XML -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="com.echo.mapper" targetProject="src">
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>

		<!-- 数据表 要根据数据库中的表来生成,tableName:数据库中表的名称 -->
		<table tableName="user"></table>
		<table tableName="country"></table>

	</context>
</generatorConfiguration>

调用配置文件(官方给出的代码,复制即可):

List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("src/generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);

在实体类的目录下会生成实体类的example类,其中封装了许多查询方式如:insert(完全插入数据)、insertSelective(带有判断的插入数据项)…
示例:
查询创建时间为null且姓名带有"老"的用户(selectByExample)

package test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.echo.bean.User;
import com.echo.bean.UserExample;
import com.echo.mapper.UserMapper;

import utils.MybatisUtils;

public class Test {
	public static void main(String[] args) {
		SqlSession session = MybatisUtils.getSession();
		UserMapper mapper = session.getMapper(UserMapper.class);
		UserExample userExample = new UserExample();
		
		//在createCriteria()下可以创建多种选择规则,且方法名称易于理解
		userExample.createCriteria().andUCreatetimeIsNull().andUUsernameLike("%老%");
	
		//直接将设置好条件的UserExample 示例传入方法selectByExample即可完成查询
		List<User> list = mapper.selectByExample(userExample);
		for(User u:list) {
			System.out.println(u);
		}
	}
}

发布了68 篇原创文章 · 获赞 12 · 访问量 5205

猜你喜欢

转载自blog.csdn.net/qq_40963076/article/details/104976017