工程的结构:
一、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> <!-- 加载数据库属性文件 --> <properties resource="SqlMap.properties" /> <!-- 1、lazyLoadingEnabled:是否延迟加载(只加载必要信息而推迟其他未明确请求数据的技术),默认值是true。 2、cacheModelsEnabled:ibatis的高速缓存,将近期使用过的数据保存到内存中,值为true或false,全局控制sqlMapClient的缓存 3、enhancementEnabled:值true或false,作用用来表示是否使用cglib中那些已经优化的javabean类来提高延迟加载的性能。 4、useStatementNameSpaces:是否使用命名空间(true/false).假如使用在引用的时候需要加上(命名空间+ID) 来访问,默认是false。 5、 errorTracingEnabled:是否启用错误日志,在开发期间建议设为"true" 以方便调试 --> <settings cacheModelsEnabled="true" lazyLoadingEnabled="true" enhancementEnabled="true" errorTracingEnabled="true" useStatementNamespaces="true" /> <transactionManager type="JDBC"><!-- type指定事务管理器:JDBC,JTA,EXTERNAL, --> <dataSource type="SIMPLE"><!-- type值由:SIMPLE,DBCP,JNDI --> <property value="${JDBC.Driver}" name="JDBC.Driver" /> <property value="${JDBC.ConnectionURL}" name="JDBC.ConnectionURL" /> <property value="${JDBC.Username}" name="JDBC.Username" /> <property value="${JDBC.Password}" name="JDBC.Password" /> </dataSource> </transactionManager> <!-- 引入所有的SQL Map配置文件,这里的路径是classpath的相对路径 --> <sqlMap resource="com/wy/pojo/Customer.xml" /> </sqlMapConfig>
二、Customer.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 namespace="cust"> <!-- 类型别名 , 为一个pojo类取一个别名, 以便在下面用时候, 直接用别名引用对象 --> <typeAlias alias="Customer" type="com.wy.pojo.Customer" /> <!-- 数据返回类型,我用的是一张表 , id 与select 标签的id一致, 就可以指定返回是多个pojo,resultMap结果映射到预先定义的resultMap中 --> <resultMap class="Customer" id="getAllCustomer"> <result property="id" column="id" /> <result property="name" column="name" /> <result property="email" column="email" /> <result property="adress" column="adress" /> <result property="phone" column="phone" /> </resultMap> <!-- 根据自己的SQL查询语句, 及传入的参数来决定它的返回类型,resutlClass="返回类型" parameterClass="传入的参数类型" --> <select id="selectAllRecords" resultClass="Customer"> <![CDATA[ select * from customer ]]> </select> <select id="selectOneRecord" parameterClass="java.lang.Integer" resultMap="getAllCustomer"> <![CDATA[ select * from customer where id = #id# ]]> </select> <!-- #id#由方法的传入参数填充 --> <insert id="insertOneRecord" parameterClass="Customer"> <!-- 序列的返回值是int类型,最好对应数据库id列;keyProperty="id"的id是对应的BEAN里面的属性 --> <selectKey resultClass="int" keyProperty="id"> select customerPKSquence.nextVal as id from dual </selectKey> <!-- 屏蔽特殊符 --> <![CDATA[ insert into customer (id,name, email, adress, phone) values (#id#,#name#, #email#, #adress#, #phone#) ]]> </insert> <update id="updateOneRecord" parameterClass="Customer"> <![CDATA[ update customer set name=#name#, email=#email#, adress=#adress#,phone=#phone# where id=#id# ]]> </update> <delete id="deleteOneRecord" parameterClass="java.lang.Integer"> <![CDATA[ delete from customer where id = #id# ]]> </delete> </sqlMap>
<statement id="statementName" [parameterClass="some.class.Name"] //表示输入的参数类型为Class [resultClass="some.class.Name"] //表示输出的参数类型为Class [parameterMap="nameOfParameterMap"] //表示输入的参数类型为Map [resultMap="nameOfResultMap"] //表示输出的参数类型为Class [cacheModel="nameOfCache"] > select * from t_user where sex = [?|#propertyName#] order by [$simpleDynamic$] </statement>
1、对于参数定义,尽量使用parameterClass,即直接将pojo作为statement的调用参数,如果输入的参数是java.util.map,那么map中的键值将作为输入参数,普通基本类型就是直接输入。
2、对于返回结果而言,尽量也使用resultClass,直接将字段名与pojo相对应。
3、而parameterMap与resultMap实现了pojo到数据库字段的映射配置,parameterMap 使用较少,而resultMap 则大多用于嵌套查询以及存储过程的 。
Customer.java
package com.wy.pojo;
public class Customer {
private Integer id;
private String name;
private String email;
private String adress;
public Customer() {
}
public Customer(Integer id, String name, String email, String adress,
String phone) {
super();
this.id = id;
this.name = name;
this.email = email;
this.adress = adress;
this.phone = phone;
}
public String getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
private String phone;
public String getEmail() {
return email;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
public void setEmail(String email) {
this.email = email;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("{");
sb.append("id:" + id + ",");
sb.append("name:'" + name + "',");
sb.append("email:'" + email + "',");
sb.append("adress:'" + adress + "',");
sb.append("phone:'" + phone + "'");
sb.append("}");
return sb.toString();
}
}
三、CustomerDaoImpl.java
package com.wy.dao.impl;
import java.sql.SQLException;
import java.util.List;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.wy.dao.ICustomerDao;
import com.wy.pojo.Customer;
import com.wy.util.SQLMapClient;
public class CustomerDaoImpl implements ICustomerDao {
// 查询数据的SQL
private static final String SELECT_All_CUSTOMERS = "cust.selectAllRecords";
private static final String SELECT_ONE_CUSTOMER = "cust.selectOneRecord";
//插入数据
private static final String INSERT_ONE_CUSTOMER = "cust.insertOneRecord";
//删除数据
private static final String DELETE_ONE_CUSTOMER = "cust.deleteOneRecord";
//修改
private static final String UPDATE_ONE_CUSTOMER = "cust.updateOneRecord";
private SqlMapClient sqlMapClient = null;
public CustomerDaoImpl() {
sqlMapClient = SQLMapClient.getSqlMapClient();
}
//插入数据
@Override
public void add(Customer student) {
try {
sqlMapClient.insert(INSERT_ONE_CUSTOMER, student);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//删除
@Override
public void deleteCustomerById(int id) {
try {
sqlMapClient.delete(DELETE_ONE_CUSTOMER, id);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//查询所有数据
@SuppressWarnings("unchecked")
@Override
public List<Customer> queryAllCustomers() {
// TODO Auto-generated method stub
List<Customer> list = null;
try {
list = sqlMapClient.queryForList(SELECT_All_CUSTOMERS);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
public Customer queryOneCustomer(Integer id){
Customer customer = null;
try {
customer = (Customer) sqlMapClient.queryForObject(SELECT_ONE_CUSTOMER,id);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return customer;
}
//修改
public void update(Customer customer) {
try {
sqlMapClient.update(UPDATE_ONE_CUSTOMER, customer);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
四、 SQLMapClint.java
package com.wy.util;
import java.io.IOException;
import java.io.Reader;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
public class SQLMapClient {
private static SqlMapClient sqlMapClient = null;
static {
String resource = "SqlMapConfig.xml";
Reader reader = null;
try {
//读取ClassPath下的配置文件
reader = Resources.getResourceAsReader(resource);
sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static SqlMapClient getSqlMapClient() {
return sqlMapClient;
}
}
log4j.properties
#定义输出级别和输出平台
log4j.rootLogger=debug,consoleAppender
#设定consoleAppender输出平台
log4j.appender.consoleAppender = org.apache.log4j.ConsoleAppender
#输出信息的级别
#log4j.appender.consoleAppender.Threshold = info
log4j.appender.consoleAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.consoleAppender.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}][%l]:%m%n
log4j.appender.consoleAppender.ImmediateFlush = true
#sqlMap 配置
log4j.logger.com.ibatis = DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource = DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner = DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate = DEBUG
log4j.logger.java.sql.Connection = DEBUG
log4j.logger.java.sql.Statement = DEBUG
log4j.logger.java.sql.PreparedStatement = DEBUG, consoleAppender
log4j.logger.java.sql.ResultSet = DEBUG
五、测试 Test.java
package com.wy.test;
import java.util.List;
import org.apache.log4j.Logger;
import com.wy.dao.ICustomerDao;
import com.wy.dao.impl.CustomerDaoImpl;
import com.wy.pojo.Customer;
public class Test {
private final static Logger log = Logger.getLogger(Test.class);
public static void main(String[] args) {
ICustomerDao customerDao = new CustomerDaoImpl();
//插入数据
Customer customers = new Customer();
customers.setName("wy");
customers.setPhone("13900000000");
customers.setEmail("wy@163.com");
customers.setAdress("北京");
customerDao.add(customers);
//修改数据
Customer cust = customerDao.queryOneCustomer(21);
cust.setName("wywy");
customerDao.update(cust);
//删除
customerDao.deleteCustomerById(4);
//查询所有数据
List<Customer> list = customerDao.queryAllCustomers();
for (Customer customer : list) {
log.info("id:" + customer.getId());
log.info("name:" + customer.getName());
log.info("phone:" + customer.getPhone());
log.info("email:" + customer.getEmail());
log.info("address:" + customer.getAdress());
}
}
}
下面是iBatis的配置关系图
遇到一个莫名其妙的错误:
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.wy.dao.impl.CustomerDaoImpl.<init>(CustomerDaoImpl.java:26)
at com.wy.test.Test.main(Test.java:16)
Caused by: java.lang.RuntimeException: Error occurred. Cause: com.ibatis.common.xml.NodeletException: Error parsing XML. Cause: org.xml.sax.SAXParseException: XML document structures must start and end within the same entity.
at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:49)
at com.ibatis.sqlmap.client.SqlMapClientBuilder.buildSqlMapClient(SqlMapClientBuilder.java:63)
at com.wy.util.SQLMapClient.<clinit>(SQLMapClient.java:19)
... 2 more
Caused by: com.ibatis.common.xml.NodeletException: Error parsing XML. Cause: org.xml.sax.SAXParseException: XML document structures must start and end within the same entity.
at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:53)
at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:46)
... 4 more
Caused by: org.xml.sax.SAXParseException: XML document structures must start and end within the same entity.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:174)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:388)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1414)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.endEntity(XMLDocumentFragmentScannerImpl.java:902)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.endEntity(XMLDocumentScannerImpl.java:605)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.endEntity(XMLEntityManager.java:1393)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1763)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanData(XMLEntityScanner.java:1242)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanComment(XMLScanner.java:756)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanComment(XMLDocumentFragmentScannerImpl.java:1036)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2945)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:225)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283)
at com.ibatis.common.xml.NodeletParser.createDocument(NodeletParser.java:157)
at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:50)
... 5 more
查了好久原因SqlMapConfig.xml中有一个注释后面没有加空格
<!-- 引入所有的SQL Map配置文件,这里的路径是classpath的相对路径-->引起。
加上空格后问题解决。不知道iBATIS为什么会出现这种问题!