您的位置:首页 > 编程语言 > Java开发

学习笔记:Spring Mvc之iBatis配置

2016-09-20 19:16 471 查看
1、 什么叫ibatis
⑴、概念(官方文档)
MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(PlanOld Java Objects,普通的Java对象)映射成数据库中的记录。
总结:dao层,操作数据库,提供对sql的封装,作用跟jdbc,hibernate类似。
2.0版本:ibatis 网址:http://ibatis.apache.org/
3.0版本:mybatis 网址:http://www.mybatis.org/
时间分隔点:2010/06/16
从3.0之后,移往google code :http://code.google.com/p/mybatis/wiki/Welcome
⑵、特点
相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半自动化”的ORM实现。 纵观目前主流的ORM,无论Hibernate 还是Apache OJB,都对数据库结构提供了较为完整的封装,提供了从POJO 到数据库表的全套映射机制。程序员往往只需定义好了POJO 到数据库表的映射关系,即可通过Hibernate 或者OJB 提供的方法完成持久层操作。程序员甚至不需要对SQL 的熟练掌握,Hibernate/OJB 会根据制定的存储逻辑,自动生成对应的SQL 并调用JDBC 接口加以执 行。 ---- 摘自官方资料的一段话
总结:ibatis是一种半自动化的ORM, 需要手工编写sql ;hibernate不需要手工编写sql。
2、 优点
⑴、iBATIS被广泛认为是最简单的一种持久化框架。
sql可以写在xml中,结构清晰,灵活配置。
⑵、文件归类,select 后的字须定义到标签中,可以实现部分代码复用。
⑶、执行sql后,返回的结果集自动封装。类似以下代码,均可省略。
while (rs.next()) {
so = new SoQueryMVO();
so.setQryFlag(rs.getString("qryFlag"));// so.setSoNbr(rs.getString("SO_NBR"));
so.setExtSoNbr(rs.getString("EXT_SO_NBR"));
so.setCoNbr(rs.getString("CO_NBR"));
so.setSoStaffName(rs.getString("SO_STAFF_NAME"));
so.setSoWorkAreaName(rs.getString("SO_WORK_AREA_NAME"));
so.setApplDate(rs.getTimestamp("APPL_DATE"));
so.setContactResult(rs.getString("CONTACT_RESULT"));
so.setBillType(rs.getString("BILL_TYPE"));
so.setPaySts(rs.getString("PAY_STS"));
res.add(so);
}
⑷、MyBatis真正的力量是在映射语句中。这里是奇迹发生的地方。对于所有的力量,SQL映射的XML文件是相当的简单。当然如果你将它们和对等功能的JDBC代码来比较,你会发现映射文件节省了大约95%的代码量。MyBatis的构建就是聚焦于SQL的,使其远离于普通的方式。
简洁的代码和简单的配置使得使用iBATIS所需的代码量可以减少到了相应JDBC代码的62%
总结一下:可以省代码。
⑸、动态sql, 没觉得有多好。
⑹、iBATIS改进了应用的设计方式以确保未来的可维护性,后期可维护性增加。
⑺、基于xml的,所以适合多平台。
iBATIS可以用任何具有完备功能的编程语言来实现。

3、 缺点
⑴、开源的东西,文档资料少,官方说明文档太简单,真正有应用价值的信息不多。
以官方文档为例:60%左右的代码讲述环境配置,即相当于我们的connection-config.xml配置,及创建一个链接, 对于服务开通来说,使用的是java代码,连接oracle库,一旦配置好环境,对于开发人员来说,专业于某些功能点,业务逻辑、流程、配置等的实现,在以后的开发过程中,其实很少关注环境。
这部分功能实现可以放到工具类中,对我们来说,文章中的说明没有什么大的使用价值。
⑵、实现了结果集自动封装,一把双刃剑。
①、返回的结果集封装结果单一,不能实现灵活封装。如Map<key=id ,value =vo >
②、不支持嵌套vo对象,如果有同名字段,会覆盖。
关联查询,需要返回很多信息,很有可能需要复写MVO,把嵌套的vo,拿出来,放到第一层的vo里面。
因为mvo改变,原来jsp页面上使用soMVO.soResMVO.resId,诸如这种形势,有可能修改前台页面。
③、以查询为例,入参单一,只有一个入参,如果有两个以上的参数,必须定义到一个对象中,感觉不灵活。
当然可以用paraMap方式进行配置,麻烦,感觉还不如定义到一个对象中。
④、部分写在dao中的逻辑,改动起来麻烦。目前的目标是只修改domIpml类,其它的尽量不修改,现在看来,
如此肯定不行了。部分复杂的逻辑靠标签无法实现。
if (!StringUtil.isBlank(so.getChbAccNbr())&& !StringUtil.isBlank(so.getAccNbr())) {
// 增加批量查询业务号码
isAvaibleCondition = true;
String tempAccNbr[] = so.getAccNbr().split(";");
List accNbrList = (List) CollectionFactory
.createCollection(CollectionFactory.COLLECTION_LIST);
for (int i = 0; i < tempAccNbr.length; i++) {
accNbrList.add(tempAccNbr[i].trim());
}
if (accNbrList.size() == 1) {
sql.append(" AND SO.SO_NBRIN ( ");
sql.append(" SELECTDISTINCT SO_NBR FROM SO_ACC_NBR where ");
if(!StringUtil.isBlank(so.getLocalNetId())) {
sql.append(" local_net_id=:lcId ");
sql.setLong("lcId", so.getLocalNetId());
sql.append(" andSTS = 'A' AND ACC_NBR LIKE :accNbr )");
sql.setString("accNbr", so.getAccNbr().trim() +"%");
} else {
sql.append(" STS ='A' AND ACC_NBR LIKE :accNbr )");
sql.setString("accNbr", so.getAccNbr().trim() +"%");
}
} else {
sql.append(" AND SO.SO_NBRIN ( ");
sql.append(" SELECTDISTINCT SO_NBR FROM SO_ACC_NBR where ");
if(!StringUtil.isBlank(so.getLocalNetId())) {
sql.append(" local_net_id=:lcId AND STS = 'A' ");
sql.setLong("lcId", so.getLocalNetId());
} else {
sql.append(" STS ='A' ");
}
int i = 0;
while (i <accNbrList.size()) {
if (i == 0)
sql.append(" AND (ACC_NBR = :accNbr");
else
sql.append(" OR ACC_NBR = :accNbr");
sql.append(""+ i + "");
sql.setString("accNbr" + i + " ", accNbrList.get(i)+ "");
i++;
}
sql.append(" ))");
}
}
⑤、其它
⑶、sql写在xml, 没有办法打断点,调试非常不方便,及其浪费时间。
有可以十几分钟写的一个大sql,完事后,调试了一天还是编译性错误,完全不夸张,很多可能。
⑷、日志输出不完全,可能是我还没有找到方法。
无法输出预编译赋值之后的sql ,查看不方便 (原来咱们系统中使用Sql.log实现)
⑸、错误信息提示异样 ,报错信息比较混乱,有些时间没有参考价值,没有起到提示作用。
⑹、文档少,现有的文档提供的标签,也不能完全满足我们的需求
如有if 没有else,形式上感到别扭,某些
大小写是否敏感?
Ibatis适用于小项目,简单的业务逻辑映射,尤其是单表操作,很方便。

下面我们来看看在Spring Mvc + Maven中如何配置iBatis。
这边给出项目的目录结构



1.在pom.xml中写入ibatis包的依赖

<dependency>
<groupId>com.ibatis</groupId>
<artifactId>ibatis2-sqlmap</artifactId>
<version>2.1.7.597</version>
</dependency>

2.配置SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<!-- 引用JDBC属性的配置文件 -->
<properties resource="datasource.properties" />
<!-- 使用JDBC的事务管理 -->
<transactionManager type="JDBC">
<!-- 数据源 -->
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="${db.driverClassName}" />
<property name="JDBC.ConnectionURL" value="${db.jdbcUrl}" />
<property name="JDBC.Username" value="${db.user}" />
<property name="JDBC.Password" value="${db.password}" />
</dataSource>
</transactionManager>
<!-- 这里可以写多个实体的映射文件 -->
<sqlMap resource="com/jeader/tad/User.xml" />
</sqlMapConfig>

注意:properties文件的路径也要在resources下

<properties resource="datasource.properties" />

3.datasource.properties

db.driverClassName=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://localhost:3306/taddb?useUnicode=true&characterEncoding=utf-8
db.user=taduser
db.password=test

4.User.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<!-- 通过typeAlias使得我们在下面使用User实体类的时候不需要写包名 -->
<typeAlias alias="User" type="com.jeader.tad.demo.User" />
<!-- 这样以后改了sql,就不需要去改java代码了 -->
<!-- id表示select里的sql语句,resultClass表示返回结果的类型 -->
<select id="selectAllUser" resultClass="User">
select * from
user
</select>
<!-- parameterClass表示参数的内容 -->
<!-- #表示这是一个外部调用的需要传进的参数,可以理解为占位符 -->
<select id="selectUserById" parameterClass="int" resultClass="User">
select * from User where id=#id#
</select>
<!-- 注意这里的resultClass类型,使用User类型取决于queryForList还是queryForObject -->
<select id="selectUserByName" parameterClass="string"
resultClass="User">
select name,birthday from User where name like
'%$name$%'
</select>
<insert id="addUser" parameterClass="User">
insert into
User(ID,USER_NAME,NAME,PASSWORD,SEX,IDENTITY_CARD_NO,BIRTHDAY,UPDATE_DATE) values
(#id#,#user_name#,#name#,#password#,#sex#,#identity_card_no#,#birthday#,#update_date#)
<selectKey resultClass="int" keyProperty="id">
select @@identity as inserted
<!-- 这里需要说明一下不同的数据库主键的生成,对各自的数据库有不同的方式: -->
<!-- mysql:SELECT LAST_INSERT_ID() AS VALUE -->
<!-- mssql:select @@IDENTITY as value -->
<!-- oracle:SELECT STOCKIDSEQUENCE.NEXTVAL AS VALUE FROM DUAL -->
<!-- 还有一点需要注意的是不同的数据库生产商生成主键的方式不一样,有些是预先生成 (pre-generate)主键的,如Oracle和PostgreSQL。
有些是事后生成(post-generate)主键的,如MySQL和SQL Server 所以如果是Oracle数据库,则需要将selectKey写在insert之前 -->
</selectKey>
</insert>
<delete id="deleteUserById" parameterClass="int">
<!-- #id#里的id可以随意取,但是上面的insert则会有影响,因为上面的name会从User里的属性里去查找 -->
<!-- 我们也可以这样理解,如果有#占位符,则ibatis会调用parameterClass里的属性去赋值 -->
delete from User where id=#id#
</delete>
<update id="updateUser" parameterClass="User">
update User set
name=#name#
where id=#id#
</update>
</sqlMap>

5.UserDao.java

package com.jeader.tad.demo;
import java.util.List;
public interface UserDao {
/**
* 添加学生信息
*
* @param user
*            学生实体
* @return 返回是否添加成功
*/
public boolean addUser(User user);
/**
* 根据学生id删除学生信息
*
* @param id
*            学生id
* @return 删除是否成功
*/
public boolean deleteUserById(int id);
/**
* 更新学生信息
*
* @param user
*            学生实体
* @return 更新是否成功
*/
public boolean updateUser(User user);
/**
* 查询全部学生信息
*
* @return 返回学生列表
*/
public List<User> selectAllUser();
/**
* 根据学生姓名模糊查询学生信息
*
* @param name
*            学生姓名
* @return 学生信息列表
*/
public List<User> selectUserByName(String name);
/**
* 根据学生id查询学生信息
*
* @param id
*            学生id
* @return 学生对象
*/
public User selectUserById(int id);
}

6.UserDaoImpl.java

package com.jeader.tad.demo;
import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;
import java.util.List;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
public class UserDaoImpl implements UserDao {
private static SqlMapClient sqlMapClient = null;
// 读取配置文件
static {
try {
Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean addUser(User user) {
Object object = null;
boolean flag = false;
try {
object = sqlMapClient.insert("addUser", user);
System.out.println("添加学生信息的返回值:" + object);
} catch (SQLException e) {
e.printStackTrace();
}
if (object != null) {
flag = true;
}
return flag;
}
public boolean deleteUserById(int id) {
boolean flag = false;
Object object = null;
try {
object = sqlMapClient.delete("deleteUserById", id);
System.out.println("删除学生信息的返回值:" + object + ",这里返回的是影响的行数");
} catch (SQLException e) {
e.printStackTrace();
}
if (object != null) {
flag = true;
}
return flag;
}
public boolean updateUser(User user) {
boolean flag = false;
Object object = false;
try {
object = sqlMapClient.update("updateUser", user);
System.out.println("更新学生信息的返回值:" + object + ",返回影响的行数");
} catch (SQLException e) {
e.printStackTrace();
}
if (object != null) {
flag = true;
}
return flag;
}
public List<User> selectAllUser() {
List<User> users = null;
try {
users = sqlMapClient.queryForList("selectAllUser", new Object());
} catch (SQLException e) {
e.printStackTrace();
}
return users;
}
public List<User> selectUserByName(String name) {
List<User> users = null;
try {
users = sqlMapClient.queryForList("selectUserByName", name);
} catch (SQLException e) {
e.printStackTrace();
}
return users;
}
public User selectUserById(int id) {
User user = null;
try {
user = (User) sqlMapClient.queryForObject("selectUserById", id);
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
}

注意:SqlMapConfig.xml文件一定要在resources下面,不然下面的语句就会报错。

Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");

7.User.java

package com.jeader.tad.demo;
import java.sql.Timestamp;
public class User {
private int id;
private String user_name;
private String name;
private String password;
private int sex;
private String identity_card_no;
private String birthday;
private Timestamp update_date;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getIdentity_card_no() {
return identity_card_no;
}
public void setIdentity_card_no(String identity_card_no) {
this.identity_card_no = identity_card_no;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public Timestamp getUpdate_date() {
return update_date;
}
public void setUpdate_date(Timestamp update_date) {
this.update_date = update_date;
}
@Override
public String toString() {
return "id=" + id + ", user_name=" + user_name + ", name=" + name + ", password=" + password + ", sex" + sex
+ ", identity_card_no" + identity_card_no + ", birthday" + birthday + ", update_date" + update_date + "\n";
}
}

8.测试类TestIbatis.java

package com.jeader.tad.demo;
import java.sql.Timestamp;
import java.util.List;
public class TestIbatis {
public static void main(String[] args) {
UserDaoImpl userDaoImpl = new UserDaoImpl();
System.out.println("测试插入");
User addUser = new User();
addUser.setId(2);
addUser.setUser_name("李四");
addUser.setName("lisi");
addUser.setPassword("test");
addUser.setSex(1);
addUser.setIdentity_card_no("320922198702221014");
addUser.setBirthday("19870101");
addUser.setUpdate_date(Timestamp.valueOf("2015-09-11 12:00:00"));
System.out.println(userDaoImpl.addUser(addUser));
System.out.println("测试根据id查询");
userDaoImpl.selectUserById(1);
System.out.println("测试模糊查询");
List<User> mohuLists = userDaoImpl.selectUserByName("李");
for (User user : mohuLists) {
System.out.println(user);
}
System.out.println("测试查询所有");
List<User> users = userDaoImpl.selectAllUser();
for (User student : users) {
System.out.println(student);
}
System.out.println("根据id删除学生信息");
System.out.println(userDaoImpl.deleteUserById(2));
System.out.println("测试更新学生信息");
User updateUser = new User();
updateUser.setId(1);
updateUser.setName("李四1");
System.out.println(userDaoImpl.updateUser(updateUser));
}
}

9.运行结果

测试插入
添加学生信息的返回值:0
true
测试根据id查询
测试模糊查询
id=0, user_name=null, name=李四1, password=null, sex0, identity_card_nonull, birthday19870101, update_datenull
测试查询所有
id=1, user_name=test, name=李四1, password=test, sex1, identity_card_no320922198702022325, birthday19870101, update_date2015-11-08 16:36:31.0
id=2, user_name=李四, name=lisi, password=test, sex1, identity_card_no320922198702221014, birthday19870101, update_date2015-09-11 12:00:00.0
根据id删除学生信息
删除学生信息的返回值:1,这里返回的是影响的行数
true
测试更新学生信息
更新学生信息的返回值:1,返回影响的行数
true
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息