前言
Java学到一定程度,框架终归是不可避免的,毕竟程序开发很多时候不是一个人的事儿。这两天学习了MyBatis框架,想着结合一下这几天学到的东西和实习的经验总结一下。大概的思路就是从JDBC的缺陷到MyBatis的介绍和运行流程,再就是Mybatis的一个增删改查小程序;然后是企业中MyBatis进行数据库开发时采用Dao方法和Mapper方法的一个介绍,最后是和Spring的一个整合。
也希望大家提出宝贵的建议。
JDBC
JDBC小程序
DBHelper(数据库连接类)
/**
* @param连接数据库
* */
public class DBHelper {
//参数配置
//public static final String url = "jdbc:mysql://127.0.0.1/test";
public static final String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf-8";
public static final String name = "com.mysql.jdbc.Driver";
public static final String user = "root";
public static final String password = "8888";
public static Connection conn= null;
public DBHelper() {
// TODO Auto-generated constructor stub
try{
Class.forName(name); //加载数据库驱动
conn = DriverManager.getConnection(url, user, password); //通过驱动管理类获取数据库链接
}catch(Exception e){
e.printStackTrace();
}
}
public static void Close(){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
testJdbc(测试SQL查询)
public class testJdbc {
private static String sql = null;
private static DBHelper db = null;
public static PreparedStatement pst = null;
public static ResultSet ret = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
db = new DBHelper(); //通过构造器连接到数据库
System.out.println(db.conn);
db.Close();
/*
//sql = "INSERT INTO `test`.`user` (`Username`, `Password`, `Age`, `Address`, `UserId`) VALUES"
// + " ('bb', '1234', '23', 'hubei', '4');"; //插入语句
//sql = "UPDATE `test`.`user` SET `Username`='ouou' WHERE `UserId`='1';"; //更新语句
sql = "DELETE * where `UserId` = '2'"; //删除语句
String sql1 = "select * from user"; //选择语句
try {
pst = db.conn.prepareStatement(sql);
pst.execute();
ret = pst.executeQuery(sql1);
while(ret.next()){
String name = ret.getString(1);
String pass = ret.getString(2);
String age = ret.getString(3);
String addr = ret.getString(4);
String id = ret.getString(5);
System.out.println(id+" "+name+" "+pass+" "+age+" "+addr);
}
}catch(SQLException e){
e.printStackTrace();
}*/
}
}
问题总结
总结网上搜集到东西和自己实际遇到的归纳为以下几点:
- 数据库频繁地连接开启和关闭,造成资源的浪费。(使用数据库连接池进行管理)
- SQL语句、preparedStatement设置参数硬编码在Java代码中,不利于系统维护。(使用xml进行配置)
- resultSet遍历结果集数据时,也存在硬编码。(将查询的结果集,自动映射成Java对象)
MyBatis
为什么选择MyBatis
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC
代码和手工设置参数以及抽取结果集。MyBatis 使用简单的 XML 或注解来配置和映射基本体,将接口和 Java的
POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。(选自官网)
- 也就是说开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc的过程代码。MyBatis通过xml或注解的方式将要执行的各种statement(statement,preparedStatement、CallableStatement)配置起来,并通过Java对象和statement中的SQL进行映射生成最终执行的SQL语句,最后又mybatis框架执行SQL并将结果映射成Java对象并返回。
MyBatis是什么
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。
MyBatis框架图
Paste_Image.pngMyBatis的运行流程
- 在SQLMapConfig.xml(mybati的全局配置文件)中配置mybatis的运行环境等信息。并在其中加载mapper.xml(sql映射文件,配置了操作数据库的SQL语句)文件。
- 通过mybatis环境等配置信息构造SQLSessionFactory会话工厂。
- 由会话工厂创建SQLSession来操作数据库。
- mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有基本执行器和缓存执行器两个实现。
- Mapped Statement也是mybatis一个底层封装对象,包装了mybatis配置信息及SQL映射信息等。mapper.xml文件中一个SQL对应一个Mapped Statement 对象,SQL的id即是Mapped Statement的id。
- Mapped Statement对SQL执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行SQL前将输入的Java对象映射至SQL中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
- Mapped Statement对SQL执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行SQL后将输出结果映射至Java对象中,输出结果映射过程相当于jdbc编程中结果的解析处理过程。
MyBatis的优缺点及Hibernate的简短比较
Mybatis和hibernate的不同之处在于它不是一个完全的ORM框架,它需要开发者自己编写SQL语句,不过mybatis可以通过xml或注解方式灵活配置要运行的SQL语句,并将Java对象和SQL语句映射生成最终执行的SQL,最后将SQL执行的结果再映射生成Java对象。
MyBatis相对于hibernate来说,学习门槛低,易于学习,灵活度也高,适合对关系数据模型要求不高的软件开发,以为其需求变化频繁。正是因为mybatis的高度灵活,所以它无法做到数据库无关性,需要实现支持多种数据库的软件则需要自定义多套SQL映射文件。
Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
所以如是说:没有最好的框架,只有最适合的框架。
简单的CRUD入门程序
导入的包:
Paste_Image.png
项目工程结构:
Paste_Image.png
输出日志信息配置(log4j.properties):
# Global logging configuration
log4j.rootLogger = DEBUG,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %5p [%t] - %m%n
全局配置文件(SqlMapConfig.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 加载属性文件 -->
<properties resource="db.properties">
</properties>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource = "sqlmap/User.xml"/>
</mappers>
</configuration>
数据库配置文件(db.properties)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8
jdbc.username=root
jdbc.password=8888
User po类:
package com.howie.po;
import java.io.Serializable;
import java.util.Date;
/**
* @param User po类
*/
public class User implements Serializable {
private int id;
private String username;// 用户名
private String sex;//性别
private Date birthday;// 生日
private String address;// 地址
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
映射文件user.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 对SQL进行分类话管理,理解SQL隔离
注意:是用mapper代理方法开发,namespace有特殊重要的作用
-->
<mapper namespace = "test">
<!-- 在映射文件中配置很多SQL语句 -->
<!-- 查找 -->
<select id = "findUserById" parameterType="int" resultType="com.howie.po.User">
SELECT * FROM test.user where id = #{value}
</select>
<!-- 添加用户 -->
<insert id="insertUser" parameterType="com.howie.po.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>
<!-- 删除用户 -->
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
</delete>
<!-- 更新用户 -->
<update id="updateUser" parameterType="com.howie.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
</mapper>
测试文件MybatisTest类
(避免麻烦,测试一个查找语句,读者感兴趣的可以自行实现其他功能)
package com.howie.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 com.howie.po.User;
public class MybatisTest {
public static void findUserByIdTest() throws IOException{
//配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建回话工厂
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SQLSession
SqlSession ss = sf.openSession();
//通过SQLSession操作数据库
//第一个参数:映射文件中statement的id,等于=namespace+statement的id
//第二个参数:制定和映射文件中所匹配的parameterType得参数
//ss.selectOne结果是与映射文件中所匹配的resultType类型的对象
User user = ss.selectOne("test.findUserById", 1);
System.out.println(user);
System.out.print(user.getAddress()+" "+user.getId()+" "+user.getUsername()+
" "+user.getSex());
System.out.println();
//释放资源
ss.close();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
findUserByIdTest();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
未完待续.......
网友评论