原生JDBC程序中问题的总结
例:使用jdbc查询mysql数据库中用户表的记录
public String searchStudent(String number) throws SQLException{
conn = DBUtil.getConnection();
String sql = "select * from student"+
" where number=?";
PreparedStatement ptmt = conn.prepareStatement(sql);
ptmt.setString(1, number);
ResultSet rs = ptmt.executeQuery();
String str = null;
while(rs.next()){
str = rs.getString("name")+" "+
rs.getString("number")+
" "+rs.getInt("math")
+" "+rs.getInt("chinese");
}
conn.close();
return str;
}
问题总结:
(1)数据库链接,使用时创建,不使用时立即释放,频繁链接数据库,造成数据库资源浪费,影响数据库性能。
常用的解决方法是通过数据库连接池来管理数据库链接
(2)将sql语句硬编码到java代码当中,如果sql语句修改,需要重写编译java代码,不利于修改维护
设想解决方案:将sql语句配置在xml文件中,
(3)向preparedStatement中设置参数,占位符与设置的参数值硬编码在java代码中,不利于系统维护
设想解决方案:将sql语句和占位符和设置变量全部配置在xml中
(4)从ResultSet结果集中遍历结果数据是,存在硬编码,将获取表的字段进行硬编码
设想解决方案:将查询结果集,自动映射成java对象
于是mybatis因此而生。
mybatis是什么?
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
Mybatis让程序员的主要精力放在sql上,通过mybatis提供的映射方式,自由灵活的生成(半自动化,大部分需要程序员编写sql)满足需求的sql语句
Mybatis可以向preparedStatement中输入的参数自动进行输入映射,将查询结果集灵活的映射成java对象(输出映射)
mybatis的特点:
-
简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件(mysql等数据库链接jar和mybatis的核心jar)+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
-
灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
-
解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
-
提供映射标签,支持对象与数据库的orm字段关系映射
-
提供对象关系映射标签,支持对象关系组建维护
-
提供xml标签,支持编写动态sql。
mybati框架原理(工作流程):
mybatis功能架构:
我们把Mybatis的功能架构分为三层:
(1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
(2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
(3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
入门程序
设置需求为:
根据用户的id来查询用户的信息
添加用户
删除用户
1.准备:
先导入两个jar包:mybatis核心jar和mysql的链接jar
2.配置log4j
log4j需要再导入log4j的jar
3.项目工程结构
SqlMapConfig.xml是mybatis的全局配置文件,sqlmap包下存放的是mapper.xml的映射文件
4.配置SqlMapConfig.xml
与原生JDBC不同,mybatis将数据库链接部分配置在SqlMapConfig.xml中,在和spring整合之后enviroments标签将被废除,该部分了解即可
<?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进行事务管理,使用mybatis进行事务控制-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.jdbc.mysql.Driver"/>
<property name="url" value="数据库URL"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments>
</configuration>
5.实现java代码:根据用户id查询用户信息
1)创建pojo类,加入get、set方法
public class User {
//属性名和数据库表字段名对应
private int id;
private String username;
private String sex;
private Date birthday;
private String address;
}
2)创建映射文件User.xml
在sqlmap包下创建User.xml(原始ibatis命名),使用mapper代理开发映射文件名称叫XXXMapper.xml(与代理接口同名同目录,后面再提), 在映射文件中配置sql语句。(mapper标签的namespace(命名空间)起到唯一标识 的作用)
<?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">
//namespace命名空间起到唯一标识 的作用
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="cn.itcast.po.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
id(select的属性):标识映射文件中的sql,将sql语句封装到mappedStatement对象中,所以将id称为statement的id
#{}表示一个占位符
#{id}:其中id表示输入的参数,参数名称就是id,
如果输入参数是简单类型,#{}中的参数名可以任意,可以是value或其他名称
parameterType 指定输入参数的类型 这里指定int形
resultType:指定sql输出的结果类型所映射的Java对象类型,select指定resultTyp
3)在SqlMapConfig.xml中加载映射文件
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mapper>
4)编写测试程序
根据用户id查询用户信息
public void findUserById() throws IOException {
//mybatis配置文件
String resource = "SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SqlSession来操作数据库
//第一个参数:映射文件中statement的id,等于=namespace+"."+statement的id
//第二个参数:指定和映射文件中所匹配的parameterType类型的参数
//sqlSession.selectOne结果是与映射文件中所匹配的resultType类型的对象
User user = sqlSession.selectOne("test.findUserById", 1);
System.out.println(user.getUsername());
//释放资源
sqlSession.close();
}
sqlSession.selectOne("test.findUserById,1) 这一句中selectOne的两个参数分别为对应的映射文件的namespace(命名空间)加上点加上在User.xml中编写的select标签的id,第二个参数1则是传入的id值,调用这个方法后就会去对应的
下面是在Use.xml中的select语句,拿出来对应上面
<select id="findUserById" parameterType="int" resultType="cn.itcast.po.User">
SELECT * FROM user WHERE id=#{id}
</select>
#{}是一个占位符,等同于"?"的作用,其中#{}在接收简单类型的数据时可以任意命名比如#{id},#{value}.....等
parameterType和resultType
在映射文件中通过parameterType指定输入参数的类型,通过resultType来指定输出结果里的类型
添加用户
1) 在User.xml中配置sql语句
<!-- 添加用户
parameterType:指定输入参数类型是POJO(包含用户信息)
#{}中指定pojo的属性名,接受到pojo对象的属性值,mybatis通过OGNL来获取对象的属性值 -->
<insert id="insertUser" parameterType="cn.itcast.po.User">
insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
value(#{id},#{username},#{birthday},#{sex},#{address})中占位符的中的变量必须对应user中的属性名,否则将插入失败,因为这里传入的是pojo对象,不是简单的数据类型。
2)测试代码
@Test
public void insertUser() throws IOException{
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("linda");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("河南郑州");
sqlSession.insert("test.insertUser",user);
//提交事务
sqlSession.commit();
System.out.println(user.getId());
sqlSession.close();
}
这里提一下,在执行查询之外的操作时,需要用sqlSession.commit()进行事务的提交,不然也会插入失败。
mybatis和hibernate本质区别和应用场景
Hibernate:是一个标准的ORM(对象关系映射)框架。入门门槛高,不需要程序员写sql,sql语句自动生成。对sql语句的优化,修改比较困难
应用场景:适用于需求变化不多的中小型的项目,比如后台管理系统,erp,orm,oa…..
Mybatis:专注的是sql本身,需要程序员自己编写sql语句,sql语句的修改和优化就比较方便。Mybatis是一个不完全的ORM框架,虽然程序员自己写sql,但是mybatis也可以实现映射(输入、输出映射)。
应用场景:主要适用于需求变化较多的项目,比如:互联网项目