欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java三大框架之Mybatis

程序员文章站 2024-03-24 17:15:04
...

三大框架之Mybatis

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

Mybatis架构

Java三大框架之Mybatis

初步接触Mybatis

mybatis下载:mybaits的代码由github.com管理,Mybatis下载地址
导入jar包 :加入mybatis核心包、依赖包、数据驱动包。junit-4.9.jar这个包是为测试方便加入的
Java三大框架之Mybatis
创建配置文件 :在classpath下创建config目录(source folder类型)log4j.properties
Java三大框架之Mybatis

# 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

mybatis默认使用log4j作为输出日志信息。

第一个mybatis程序

在config下创建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>
	<!-- 和spring整合后 environments配置将废除-->
	<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:3306/db_test1?characterEncoding=utf-8" />
				<property name="username" value="root" />
				<property name="password" value="root" />
			</dataSource>
		</environment>
	</environments>
</configuration>

创建一个User实体类

private int id;
private String name;
private String password;
private String sex;
private int  age;

sql映射文件User.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="test">
</mapper>

namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。
**mybatis框架需要加载映射文件,将User.xml添加在SqlMapConfig.xm

<mappers>
		<mapper resource="sqlmap/User.xml"/>
</mappers>

在User.xml配置根据id获取用户信息

<select id="findUserById" parameterType="int" resultType="com.yun.mybatis.domain.User">
		select * from user where id=#{id}
	</select>

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

测试程序(新建一个测试类)

public class MyTest {
	SqlSessionFactory ssf = null;
	@Before
	public void creatFactory(){
		InputStream input = null;
			try {
				input = Resources.getResourceAsStream("SqlMapConfig.xml");
			} catch (IOException e) {
				e.printStackTrace();
			}
		ssf = new SqlSessionFactoryBuilder().build(input);
	}
	/** 通过id查找*/
	@Test
	public void testFindUserById(){
		SqlSession session =ssf.openSession();
		//System.out.println(session);
		User user = session.selectOne("test.findUserById", 8);
		System.out.println(user);
		session.close();
	}
}

根据用户名查询

<select id="findUserByName" parameterType="string" resultType="com.yun.mybatis.domain.User">
		select * from user where name like "%${value}%"
</select>

parameterType:定义输入到sql中的映射类型,value使{value}表示使用参数将{value}替换,做字符串的拼接。
注意:如果是取简单数量类型的参数,括号中的值必须为value
resultType:定义结果映射类型。

测试代码

@Test
	public void testFindUserByName(){
		SqlSession session =ssf.openSession();
		
		List<User>  userList = session.selectList("test.findUserByName", "xiao");
		System.out.println(userList);
		session.close();
	}

#{}和${}

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。一般用在=之后。
sql{}表示拼接sql串,通过{}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, pojoparameterType{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,{}括号中只能是value。一般用在like之后。

5.6.2parameterType和resultType

parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。

5.6.3selectOne和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可以查询一条或多条记录

添加用户

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
	  insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
	</insert>
@Test
	public void testInsert() {
		// 数据库会话实例
		SqlSession sqlSession = null;
			// 创建数据库会话实例sqlSession
			sqlSession = sqlSessionFactory.openSession();
			// 添加用户信息
			User user = new User();
			user.setUsername("张小明");
			user.setAddress("河南郑州");
			user.setSex("1");
			user.setPrice(1999.9f);
			sqlSession.insert("test.insertUser", user);
			//提交事务
			sqlSession.commit();
			}

mysql自增主键返回

  1. 通过修改sql映射文件,可以将mysql自增主键返回
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
		<!-- selectKey将主键返回,需要再返回 -->
		<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
			select LAST_INSERT_ID()
		</selectKey>
	   insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address});
	</insert>
  1. 添加selectKey实现将主键返回

keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

Mysql使用 uuid实现主键
需要增加通过select uuid()得到uuid值

<insert  id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE" keyProperty="id">
	select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address)values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

注意这里使用的order是“BEFORE”

删除用户

  1. 映射文件
<!-- 删除用户 -->
	<delete id="deleteUserById" parameterType="int">
		delete from user where id=#{id}
	</delete>
  1. 5.8.2测试程序
// 根据id删除用户
	@Test
	public void testDelete() {
		// 数据库会话实例
		SqlSession sqlSession = null;
			// 创建数据库会话实例sqlSession
			sqlSession = sqlSessionFactory.openSession();
			// 删除用户
			sqlSession.delete("test.deleteUserById",18);
			// 提交事务
			sqlSession.commit();
			sqlSession.close();
	}

修改用户

  1. 映射文件
<!-- 更新用户 -->
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
	update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
  1. 测试程序
public void testUpdate() {
		// 数据库会话实例
		SqlSession sqlSession = null;
			// 创建数据库会话实例sqlSession
			sqlSession = sqlSessionFactory.openSession();
			// 添加用户信息
			User user = new User();
			user.setId(16);
			user.setUsername("张小明");
			user.setAddress("河南郑州");
			user.setSex("1");
			user.setPrice(1999.9f);
			sqlSession.update("test.updateUser", user);
			// 提交事务
			sqlSession.commit();
			sqlSession.close();
		}

1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。

2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。