在做这个入门程序之前,我们来顶一下需求,根据需求来写程序会不会很有感觉呢?
一、 需求
实现以下功能:
根据用户id查询一个用户信息
根据用户名称模糊查询用户信息列表
添加用户
更新用户
删除用户
1、 第一步:创建java工程
使用eclipse创建java工程,jdk使用1.7。
2、 第二步:加入jar包
加入mybatis核心包、依赖包、数据驱动包。
3、 第三步:log4j.properties
在classpath下创建log4j.properties如下:
<span style="color: rgb(0, 180, 0); font-family: Arial, Helvetica, sans-serif; background-color: rgb(217, 217, 217);"># Global loggingconfiguration</span>
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作为输出日志信息。
4、 第四步:SqlMapConfig.xml
在classpath下创建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/mybatis?characterEncoding=utf-8"/>
<property name="username"
value="root"/>
<property name="password"
value="mysql"/>
</dataSource>
</environment>
</environments>
</configuration>
SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。
5、 第五步:pojo类
Pojo类作为mybatis进行sql映射使用,pojo类通常与数据库表对应,User.java如下:
Public class User {
private int id;
private String
username;//
用户姓名
private String
sex;// 性别
private Date
birthday;//
生日
private String
address;//
地址
get/set……
6、 第六步:程序编写
6.1 查询
6.1.1 映射文件:
在classpath下的sqlmap目录下创建sql映射文件Users.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语句,后面会讲另一层非常重要的作用。
在User.xml中添加:
<!--
根据id获取用户信息 -->
<select id="findUserById"parameterType="int"
resultType="com.mybatis.pojo.User">
select * from user where id = #{id}
</select>
<!-- 自定义条件查询用户列表 -->
<select id="findUserByUsername"parameterType="java.lang.String"
resultType="com.mybatis.pojo.User">
select * from user where username like ‘%${value}%‘
</select>
parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。
resultType:定义结果映射类型。
6.1.2 加载映射文件
mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml,如下:
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>
6.1.3 测试程序:
public
class Mybatis_first {
//会话工厂
private SqlSessionFactory
sqlSessionFactory;
@Before
public
void createSqlSessionFactory()
throws IOException {
// 配置文件
String resource =
"SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
// 根据 id查询用户信息
@Test
public
void testFindUserById() {
// 数据库会话实例
SqlSessionsqlSession =
null;
try {
// 创建数据库会话实例sqlSession
sqlSession=
sqlSessionFactory.openSession();
// 查询单个记录,根据用户id查询用户信息
Useruser = sqlSession.selectOne("test.findUserById", 10);
// 输出用户信息
System.out.println(user);
}catch(Exception e) {
e.printStackTrace();
}finally{
if (sqlSession !=
null) {
sqlSession.close();
}
}
}
// 根据用户名称模糊查询用户信息
@Test
public
void testFindUserByUsername() {
// 数据库会话实例
SqlSessionsqlSession =
null;
try {
// 创建数据库会话实例sqlSession
sqlSession=
sqlSessionFactory.openSession();
// 查询单个记录,根据用户id查询用户信息
List<User>list = sqlSession.selectList("test.findUserByUsername",
"张");
System.out.println(list.size());
}catch(Exception e) {
e.printStackTrace();
}finally{
if (sqlSession !=
null) {
sqlSession.close();
}
}
}
}
6.1.4、#{}和${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
6.1.5、parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
6.1.6、selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned byselectOne(), but found: 3
atorg.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查询一条或多条记录。
6.2 添加
6.2.1 映射文件
在SqlMapConfig.xml中添加:
<!--
添加用户 -->
<insert id="insertUser"parameterType="com.mybatis.pojo.User">
<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>
6.2.2 测试程序
//
添加用户信息
@Test
public
void testInsert() {
// 数据库会话实例
SqlSession sqlSession =
null;
try {
// 创建数据库会话实例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();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession !=
null) {
sqlSession.close();
}
}
}
6.2.3 mysql自增主键返回
通过修改sql映射文件,可以将mysql自增主键返回:
<insertid="insertUser"parameterType="com.mybatis.pojo.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>
添加selectKey实现将主键返回
keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID()是mysql的函数,返回auto_increment自增列新记录id值。
6.2.4 mysql使用uuid()实现主键
需要增加通过select uuid()得到uuid值
<insert id="insertUser" parameterType="com.mybatis.pojo.User">
<selectKeyresultType="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”
6.2.5 Oracle使用序列生成主键
首先自定义一个序列且用于生成主键,selectKey使用如下:
<insert id="insertUser" parameterType="com.mybatis.pojo.User">
<selectKeyresultType="java.lang.Integer" order="BEFORE"
keyProperty="id">
SELECT 自定义序列.NEXTVAL FROM DUAL
</selectKey>
insert into user(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
注意这里使用的order是“BEFORE”
6.3 删除
6.3.1 映射文件:
<!--
删除用户 -->
<delete id="deleteUserById"parameterType="int">
delete from user where id=#{id}
</delete>
6.3.2 测试程序:
//
根据id删除用户
@Test
public
void
testDelete(){
// 数据库会话实例
SqlSession sqlSession =
null;
try {
// 创建数据库会话实例sqlSession
sqlSession =
sqlSessionFactory.openSession();
// 删除用户
sqlSession.delete("test.deleteUserById",18);
// 提交事务
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession !=
null) {
sqlSession.close();
}
}
}
6.4修改
6.4.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>
6.4.2 测试程序
//
更新用户信息
@Test
public
void
testUpdate(){
// 数据库会话实例
SqlSession sqlSession =
null;
try {
// 创建数据库会话实例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();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession !=
null) {
sqlSession.close();
}
}
}
7 Mybatis解决jdbc编程的问题
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定义输出结果的类型。
8 与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需要具有很强的经验和能力才行。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。