创建WebProject之后先把mybatis-3.2.2.zip里的mybatis-3.2.2.jar包和lib里的asm-3.3.1.jar、cglib-2.2.2.jar、commons-logging-1.1.1.jar、javassist-3.17.1-GA.jar、log4j-1.2.17.jar、slf4j-api-1.7.5.jar、slf4j-log4j12-1.7.5.jar再加一个数据库驱动ojdbc14.jar共9个包放入Web-INFO的lib包下.
再配置XML的核心配置文件,名字可以随意起,在这里我起名config.xml.然后从MyBatis用户指南.pdf里复制一下以下代码:
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="username" value="scott"/>
<property name="password" value="orcl"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="cn/jbit/bean/EmpMapper.xml"/>
</mappers>
</configuration>
其中里面的driver、url、username、password、的值需要自己更改.
然后再创建测试实体类Emp;
package cn.jbit.bean;
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private Double sal;
private Double comm;
public Emp() {
}
@Override
public String toString() {
return "Emp [empno=" + empno + ", ename=" + ename + ", job=" + job
+ ", mgr=" + mgr + ", sal=" + sal
+ ", comm=" + comm + "]";
}
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Integer getMgr() {
return mgr;
}
public void setMgr(Integer mgr) {
this.mgr = mgr;
}
public Double getSal() {
return sal;
}
public void setSal(Double sal) {
this.sal = sal;
}
public Double getComm() {
return comm;
}
public void setComm(Double comm) {
this.comm = comm;
}
}
然后再配置映射文件EmpMapper.xml在bean包下(和实体类同一个包下):
<?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="cn.jbit.bean.EmpMapper">
<select id="selectEmp" parameterType="int" resultType="cn.jbit.bean.Emp">
select * from Emp where empno = #{id}
</select>
<select id="eall" resultType="cn.jbit.bean.Emp">
select * from Emp
</select>
</mapper>
其中namespace="cn.jbit.bean.EmpMapper"的为路径包名, EmpMapper名随便起.
select id="selectEmp" id名随便起一个id可以映射一个方法
(<select id=selectEmp" parameterType="int" resultType="cn.jbit.bean.Emp">
select * from Emp where empno = #{id}
</select>
是根据条件查询一个实体类的配置)
(<select id="eall" resultType="cn.jbit.bean.Emp">
select * from Emp
</select>是查询一个实体集合的配置
)
************************************************************************************************
从pdf里找到:
String resource = "org/mybatis/example/Configuration.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlMapper = new SqlSessionFactoryBuilder().build(reader);就可以去测试了
测试:
public class Test {
SqlSessionFactory factory;
public Test() throws IOException {
String resource = "config.xml";
Reader reader = Resources.getResourceAsReader(resource);
factory = new SqlSessionFactoryBuilder().build(reader);
}
//查询单个
@org.junit.Test
public void test1() throws IOException{
SqlSession session = factory.openSession();
Emp emp = session.selectOne("cn.jbit.bean.EmpMapper.eid",7788);
System.out.println(emp);
}
//查询集合
@org.junit.Test
public void test2() throws IOException{
String resource = "config.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = build.openSession();
List<Emp> emps=session.selectList("cn.jbit.bean.EmpMapper.eall");
for (Emp emp : emps) {
System.out.println(emp);
}
}
//插入数据
@org.junit.Test
public void test3(){
SqlSession ses=factory.openSession();
Emp emp=new Emp();
emp.setEname("sbsp");
emp.setJob("sbgz");
int i = ses.insert("cn.jbit.bean.EmpMapper.save",emp);
ses.commit();
System.out.println(i);
}
//更改数据
@org.junit.Test
public void test4(){
SqlSession ses=factory.openSession();
Emp emp=new Emp();
emp.setEmpno(5);
emp.setEname("傻逼");
int i = ses.update("cn.jbit.bean.EmpMapper.update",emp);
ses.commit();
System.out.println(i);
}
//删除数据
@org.junit.Test
public void test5(){
SqlSession ses=factory.openSession();
int i = ses.delete("cn.jbit.bean.EmpMapper.del",5);
ses.commit();
System.out.println(i);
}
}
***************************************************************************************************************************
期间如果想要运行的快一点的话,先找到mybatis-3.2.2.jar包用右键选择打开方式选择压缩文件管理器WinRAR打开, mybatis-3.2.2.jarorgapacheibatisuilderxml下找到
mybatis-3-config.dtd和mybatis-3-mapper.dtd然后点击Window→preferences→搜索里面输入XML→XML Catalog找到User Specified Entries→add然后在Location:选择FileSystem找到刚才的mybatis-3-config.dtd,然后Key type= Public ID然后Key的值为:项目里config.xml里<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
取public后双引号里的值: -//mybatis.org//DTD Config 3.0//EN.
然后按照同样的方法配置mybatis-3-mapper.dtd
****************************************************************************************************************************
*****************************************************************************************************************************
最容易出错的地方(1): <delete id="del" parameterType="int">
delete from Emp where empno=#{id} //这里没有分号,加上会报错
</delete>
(2) delete from Emp where empno=#{id} //传参数的时候应该以#号加大括号,容易写成$符号.
***********************************************************************************************************************************
在有映射配置文件的基础上还可以用接口进行封装:接口里的方法和EmpMapper.xml里差不多:
我的映射文件EmpMapper.xml
***********************************************************************************************************************************
在有映射配置文件的基础上还可以用接口进行封装:接口里的方法和EmpMapper.xml里差不多:
我的映射文件EmpMapper.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="cn.jbit.bean.EmpMapper">
<select id="selectEmp" parameterType="int" resultType="cn.jbit.bean.Emp">
select * from
Emp where empno = #{id}
</select>
<select id="eall" resultType="cn.jbit.bean.Emp">
select * from Emp
</select>
//这里的my_seq.nextval是我创建的一个序列如果换数据库得注意,不然会报错
<insert id="save" parameterType="cn.jbit.bean.Emp">
insert into Emp (EMPNO, ENAME,
JOB)
values (my_seq.nextval, #{ename}, #{job})
</insert>
<update id="update" parameterType="cn.jbit.bean.Emp">
update Emp set ename=#{ename} where empno=${empno}
</update>
<delete id="del" parameterType="int">
delete from Emp where empno=#{id}
</delete>
</mapper>
我的接口:
public interface EmpMapper {
Emp selectEmp(int empno);
List<Emp> eAll();
void save(Emp emp);
void update(Emp emp);
void del(int empno);
}
测试的时候这么测试:
//测试接口
@org.junit.Test
public void save(){
SqlSession ses=factory.openSession();
EmpMapper mapper = ses.getMapper(EmpMapper.class);
Emp emp=new Emp();
emp.setEname("sbsp");
emp.setJob("sbgz");
mapper.save(emp);
ses.commit();
}
********************************************************************************************************************************
还可以不用映射XML文件直接用注解:
public interface EmpMapper {
//可以用注解,注解不能和映射文件共存,得把映射文件删了,注解功能有限
//注解不过是把映射文件里的SQL语句挪用到了注解里面而已
@Select("select * from Emp where empno = #{id}")
Emp selectEmp(int empno);
@Select("select * from Emp")
List<Emp> eAll();
//这里的my_seq.nextval是我创建的一个序列如果换数据库得注意,不然会报错
@Insert("insert into Emp (EMPNO, ENAME,JOB) values (my_seq.nextval, #{ename}, #{job})")
void save(Emp emp);
@Update("update Emp set ename=#{ename} where empno=#{empno}")
void update(Emp emp);
@Delete("delete from Emp where empno=#{id}")
void del(int empno);
}
Config.xml的映射源也要改动把resource换为class
<mappers>
<mapper resource="cn/jbit/bean/EmpMapper.xml" />
<!-- <mapper class="cn.jbit.bean.EmpMapper" /> -->
</mappers>
***********************************************************************************************************************************
还可以根据mybatis-3-config.dtd里的配置顺序就行Properties、settings(如:log4j)、和typeAliases(别名的配置),记住一定得按mybatis-3-config.dtd得顺序,顺序如下:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
配置jdbc.properties里的配置信息为:
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
username=scott
password=123
那么我原来的config.xml配置文件里需要改动的地方为:
<!-- 引入外部properties文件 -->
<properties resource="jdbc.properties">
</properties>
然后driver、url、username、password、等就直接从配置文件里读;
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
-----------------------------------------------------------------------------------------------------------------------------------
配置log4j.properties里的配置信息为:
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %u20105p [%c] u2010 %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
那么我原来的config.xml配置文件里需要加上:
<!-- mybatis 系统设置 -->
<settings>
<setting name="logImpl" value="LOG4J" />
</settings>
切记如果有properties配置文件的配置信息的话,log4j的配置信息要在其下,按照顺序.
------------------------------------------------------------------------------------------------------------------------------------
配置typeAliases
只需要在config.xml配置文件里需要加上
<!-- 别名 -->
<typeAliases>
<typeAlias type="cn.jbit.bean.Emp" alias="Emp" />
</typeAliases>
后,映射文件EmpMapper.xml里的所有parameterType="cn.jbit.bean.Emp"就可以改为别名: resultType="Emp"了.
切记如果有properties配置文件和log4j的配置信息的话, typeAliases的配置信息要在他们俩之下,按照顺序.
------------------------------------------------------------------------------------------------------------------------------------
最后我整个的config.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>
<!-- 引入外部properties文件 -->
<properties resource="jdbc.properties">
</properties>
<!-- mybatis 系统设置 -->
<settings>
<setting name="logImpl" value="LOG4J" />
</settings>
<!-- 别名 -->
<typeAliases>
<typeAlias type="cn.jbit.bean.Emp" alias="Emp" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="cn/jbit/bean/EmpMapper.xml" />
<!-- <mapper class="cn.jbit.bean.EmpMapper" /> -->
</mappers>
</configuration>
***********************************************************************************************************
如果实体类和数据库列名不一致,那么有两种解决方法
1:更改别名 select ename as name from Emp
EmpMapper.xml映射文件配置为:
<select id="selectEmp" parameterType="int" resultType="cn.jbit.bean.Emp">
select empno,ename name,job,hiredate,sal,comm,deptno from
Emp where empno = #{id}
</select>
2:用resultMap <select id="selectEmp2" parameterType="int"
resultMap="result">sql语句</select>
<resultMap type="cn.jbit.bean.Emp" id="result"> <id
property="empno" column="empno"></id> <result property="name"
column="ename"/> <result property="job" column="job"/></resultMap>
EmpMapper.xml映射文件配置为:
<select id="selectEmp2" parameterType="int" resultMap="result">
select empno,ename ,job,hiredate,sal,comm,deptno from
Emp where empno = #{id}
</select>
<resultMap type="cn.jbit.bean.Emp" id="result">
<id property="empno" column="empno"></id>
<result property="name" column="ename"/>
<result property="job" column="job"/>
</resultMap>
测试是使用接口会更方便一点,省去了session.selectone()每次都需要填写<mapper namespace="cn.jbit.bean.EmpMapper">里的值:
我的接口(接口里的方法和映射文件里的<select id=””>的值对应)
public interface EmpMapper {
Emp selectEmp(int empno);
Emp selectEmp2(int empno);
Emp manytoOne(int empno);
Emp mto(int empno);
}
不用接口得这么查:
//查询单个
@org.junit.Test
public void test1() throws IOException{
SqlSession session = factory.openSession();
Emp emp = session.selectOne("cn.jbit.bean.EmpMapper.selectEmp",7788);
System.out.println(emp);
}
用了接口就可以:
@org.junit.Test
public void test1() {
SqlSession session = factory.openSession();
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = mapper.selectEmp(7788);
System.out.println(emp.getName());
}
**************************************************************************************************************
<!-- 两条SQL语句的多对一配置 -->
<select id="manytoOne" parameterType="int" resultMap="resultdept">
select * from Emp where empno=#{id}
</select>
<resultMap type="cn.jbit.bean.Emp" id="resultdept">
<id property="empno" column="empno"></id>
<result property="name" column="ename" />
<result property="job" column="job" />
<association property="dept" column="deptno" javaType="cn.jbit.bean.Dept"
select="selectDept"></association>
</resultMap>
<select id="selectDept" resultType="cn.jbit.bean.Dept">
select * from Dept where deptno=#{id}
</select>
<!-- 一条SQL语句的多对一配置 -->
<select id="mto" parameterType="int" resultMap="resultmap1">
select * from Emp e left join Dept d on e.deptno=d.deptno where
e.empno=#{id}
</select>
<resultMap type="cn.jbit.bean.Emp" id="resultmap1">
<id property="empno" column="empno" />
<result property="name" column="ename" />
<result property="job" column="job" />
<association property="dept" column="deptno" javaType="cn.jbit.bean.Dept">
<id property="deptno" column="deptno" />
<result property="dname" column="dname" />
</association>
</resultMap>
<!-- 两条SQL语句的一对多 -->
<select id="onetomany" parameterType="int" resultMap="resultonetomany">
select * from Dept where deptno=#{id}
</select>
<resultMap type="cn.jbit.bean.Dept" id="resultonetomany">
<id property="deptno" column="deptno"></id>
<result property="dname" column="dname"/>
<collection property="emps" column="deptno" ofType="cn.jbit.bean.Emp" select="empjihe"></collection>
</resultMap>
<select id="empjihe" resultType="cn.jbit.bean.Emp">
select * from Emp where deptno=#{id}
</select>
<!-- 一条SQL语句的一对多 -->
<select id="otm" parameterType="int" resultMap="resultotm">
select * from Dept d left join Emp e on d.deptno=e.deptno where d.deptno=#{id}
</select>
<resultMap type="cn.jbit.bean.Dept" id="resultotm">
<id property="deptno" column="deptno"></id>
<result property="dname" column="dname"/>
<collection property="emps" column="deptno" ofType="cn.jbit.bean.Emp">
<id property="empno" column="empno"></id>
<result property="name" column="ename" />
<result property="job" column="job" />
</collection>
</resultMap>
***************************************************************************************************************
配置信息:
<!-- 使用动态SQL完成复杂操作 -->
<select id="selectLike" parameterType="cn.jbit.bean.Emp" resultType="cn.jbit.bean.Emp">
select empno,ename name,job,hiredate,sal,comm from Emp where 1=1
<if test="name!=null">
and ename like #{name}
</if>
</select>
测试类:
//使用动态SQL完成复杂操作
@org.junit.Test
public void test7(){
SqlSession ses=factory.openSession();
EmpMapper mapper = ses.getMapper(EmpMapper.class);
Emp emp=new Emp();
emp.setName("%S%");
List<Emp> list = mapper.selectLike(emp);
System.out.println(list.size());
}
**********************************************************************************************************************
//测试一级缓存
@org.junit.Test
public void test8() {
SqlSession session = factory.openSession();
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = mapper.selectEmp(7788);
System.out.println(emp.getName());
System.out.println("-----------------------------");
EmpMapper mapper2 = session.getMapper(EmpMapper.class);
Emp emp2 = mapper2.selectEmp(7788);
System.out.println(emp2.getName());
}
这时的SQL语句只查询了一次:
log4j:ERROR Unexpected char [‐] at position 10 in conversion patterrn.
2014-11-18 12:07:36,615 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ooo Using Connection [oracle.jdbc.driver.T4CConnection@7976c1]
2014-11-18 12:07:36,630 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ==> Preparing: select empno,ename name,job,hiredate,sal,comm,deptno from Emp where empno = ?
2014-11-18 12:07:36,789 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ==> Parameters: 7788(Integer)
SCOTT
-----------------------------
SCOTT
把Session关闭之后再查询:
session.close();
session = factory.openSession();
mapper = session.getMapper(EmpMapper.class);
Emp emp2 = mapper.selectEmp(7788);
System.out.println(emp2.getName());
SQL语句查询了两次:
log4j:ERROR Unexpected char [‐] at position 10 in conversion patterrn.
2014-11-18 12:13:59,726 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ooo Using Connection [oracle.jdbc.driver.T4CConnection@7976c1]
2014-11-18 12:13:59,742 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ==> Preparing: select empno,ename name,job,hiredate,sal,comm,deptno from Emp where empno = ?
2014-11-18 12:13:59,916 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ==> Parameters: 7788(Integer)
SCOTT
-----------------------------
2014-11-18 12:13:59,978 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ooo Using Connection [oracle.jdbc.driver.T4CConnection@7976c1]
2014-11-18 12:13:59,978 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ==> Preparing: select empno,ename name,job,hiredate,sal,comm,deptno from Emp where empno = ?
2014-11-18 12:13:59,978 [main] %‐5p [cn.jbit.bean.EmpMapper.selectEmp] ‐ ==> Parameters: 7788(Integer)
SCOTT
***********************************************************************************************************************
测试二级缓存:
只需要在映射文件<mapper namespace="cn.jbit.bean.EmpMapper"> </mapper>里第一行加上<cache></cache>就行了.注意二级缓存需要实体类序列化.
如果想配置也可以多配置一下:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"></cache>
其中:
* LRU – 最近最少使用:移出最近最长时间内都没有被使用的对象。
* FIFO –先进先出:移除最先进入缓存的对象。
* SOFT – 软引用: 基于垃圾回收机制和软引用规则来移除对象(空间内存不足时才进行回
收)。
* WEAK – 弱引用: 基于垃圾回收机制和弱引用规则(垃圾回收器扫描到时即进行回
收)。
默认使用LRU。
flushInterval :设置任何正整数,代表一个以毫秒为单位的合理时间。默认是没有设置,因此
没有刷新间隔时间被使用,在语句每次调用时才进行刷新。
Size:属性可以设置为一个正整数,您需要留意您要缓存对象的大小和环境中可用的内存空间。
默认是1024。
readOnly:属性可以被设置为true 或false。只读缓存将对所有调用者返回同一个实例。因此这
些对象都不能被修改,这可以极大的提高性能。可写的缓存将通过序列化来返回一个缓存对象的
拷贝。这会比较慢,但是比较安全。所以默认值是false。