2017.2.1-2017.2.2
MyBatis能干什么?
它是一个持久层框架(就是将数据保存到数据库中),更加便携的操作数据库,比如将数据库返回的内容进行List或实体类的封装,将执行操作的SQL语句配置到xml文件中,这样有利于代码的后期维护,使代码的分层更加明确,它还具有优化查询效率的缓存等功能。
为什么要使用MyBatis?
举个简单的例子,在使用传统的jdbc代码时,需要写上DAO层代码,在DAO层代码中将数据表中的数据封装到自定义的实体类中。这样给代码维护带来了问题。但MyBatis和hibernate解决了这样的问题,使用它们做查询时,可以自动地将数据表中的数据记录封装到实体或Map中,在将它们放入List返回
使用MyBatis Generator工具逆向
http://blog.csdn.net/zcwforali/article/details/54809088
第一个项目
前期资源准备
- mybatis.jar
- mysql-connector-java-5.1.12-bin.jar
新建项目
编写mybatis配置文件:mybatis-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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql:///mybatis" /> <property name="username" value="root" /> <property name="password" value="951029" /> </dataSource> </environment> </environments> <mappers> <mapper resource="orm/UserinfoMapper.xml"/> </mappers> </configuration>
用mybatis generator插件生成代码,右键生成代码
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration > <classPathEntry location="F:\java\mybatis\WebRoot\WEB-INF\lib\mysql-connector-java-5.1.12-bin.jar" /> <context id="context1" > <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql:///mybatis?characterEncoding=utf-8" userId="root" password="951029" /> <javaModelGenerator targetPackage="orm" targetProject="mybatis/src" /> <sqlMapGenerator targetPackage="orm" targetProject="mybatis/src" /> <javaClientGenerator targetPackage="orm" targetProject="mybatis/src/" type="XMLMAPPER" /> <table schema="dbo" tableName="userinfo" > <generatedKey column="id" sqlStatement="jdbc" identity="true"/> </table> </context> </generatorConfiguration>
5.写servlet代码执行数据操作
package controller; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; 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 orm.Userinfo; public class test extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("hello"); try{ Userinfo userinfo=new Userinfo(); userinfo.setUsername("zcw"); userinfo.setPassword("123"); String resource="mybatis-config.xml"; InputStream inputStream=Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession=sqlSessionFactory.openSession(); sqlSession.insert("insert",userinfo); sqlSession.commit(); sqlSession.close(); }catch(IOException e){ e.printStackTrace(); } } }
6.浏览器访问servlet
SqlSession对象获取封装类
package Common;
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;
public abstract class GetSqlSession {
public static SqlSession getSqlSession() throws IOException{
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
return sqlSession;
}
}
对MySQL进行CRUD
前面已经执行了插入操作,就不再演示了,后面的代码只更改test类的代码。
查询(R)操作
Userinfo userinfo=new Userinfo();
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
userinfo=sqlSession.selectOne("selectByPrimaryKey",1); //获得主键为1的userinfo对象,"selectByPrimaryKey"是从UserinfoMapper.xml得知的
System.out.println(userinfo.getUsername());
sqlSession.commit();
sqlSession.close();
更新(U)操作
userinfo=sqlSession.selectOne("selectByPrimaryKey",1); //获得要更改的数据
userinfo.setPassword("666"); //更改他的字段
sqlSession.update("updateByPrimaryKeySelective",userinfo); //执行
删除(D)操作
sqlSession.delete("deleteByPrimaryKey",5);
MyBatis核心对象的生命周期与封装
- SqlSessionFactoryBuilder可以被JVM虚拟机所实例化、使用或销毁。一旦使用SqlSessionFactoryBuilder创建SQLSessionFactory后,SqlSessionFactoryBuilder类就不需要存在了。因此SqlSessionFactoryBuilder对象的最佳使用范围是在方法内。
- SqlSessionFactory对象由SqlSessionFactoryBuilder对象创建。一旦创建SqlSessionFactory对象,该实例应该在应用执行期间都存在。所以应用它的最佳方式是写一个单例模式,或使用Spring框架来实现单例模式。
SqlSession对象由SqlSessionFactory类创建,每一个线程都应该有自己的SqlSession实例。SqlSession的实例不能共享,它也是线程不安全的,所以千万不要在Servlet中声明一个该对象的实例变量。关闭SqlSession很重要,应该确保使用finally块来关闭它。
public class insertUserinfo extends HttpServlet{ public void doGet(...)throws ServletException,IOException{ SqlSession sqlSession=GetSqlSession.getSqlSession(); try{ //sqlSession curd code sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); }finally{ sqlSession.close(); } } }
创建GetSqlSessionFactory.java类
package db;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
/*
* 使用单例模式来获取SqlSessionFactory对象
*/
public class GetSqlSessionFactory {
private static SqlSessionFactory sqlSessionFactory;
private GetSqlSessionFactory() {
}
synchronized public static SqlSessionFactory getSqlSessionFactory() {
try {
if (sqlSessionFactory == null) {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources
.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
} else {
}
} catch (IOException e) {
e.printStackTrace();
}
return sqlSessionFactory;
}
}
创建GetSQLSession.java类
package db;
import org.apache.ibatis.session.SqlSession;
public class GetSqlSession {
private static ThreadLocal<SqlSession> tl=new ThreadLocal<SqlSession>();
public static SqlSession getSession(){
SqlSession sqlSession=tl.get();
if(sqlSession==null){
sqlSession=GetSqlSessionFactory.getSqlSessionFactory().openSession();
tl.set(sqlSession);
}
else{
}
System.out.println("获得sqlSession对象的hashCode:"+sqlSession.hashCode());
return sqlSession;
}
public static void commit(){
if(tl.get()!=null){
tl.get().commit();
tl.get().close();
tl.set(null);
System.out.println("提交了!");
}
}
public static void rollback(){
if(tl.get()!=null){
tl.get().rollback();
tl.get().close();
tl.set(null);
System.out.println("回滚了!");
}
}
}
创建DBOperate.java类
package db;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
public class DBOperate {
public int insert(String sql,Map valueMap){
SqlSession sqlSession=GetSqlSession.getSession();
return sqlSession.insert(sql,valueMap);
}
public int delete(String sql,Map valueMap){
SqlSession sqlSession=GetSqlSession.getSession();
return sqlSession.delete(sql,valueMap);
}
public int update(String sql,Map valueMap){
SqlSession sqlSession=GetSqlSession.getSession();
return sqlSession.update(sql,valueMap);
}
public List<Map> select(String sql,Map valueMap){
SqlSession sqlSession=GetSqlSession.getSession();
return sqlSession.selectList(sql,valueMap);
}
}
MyBatis3常用技能
- 使用Properties对象连接数据库
- 动态SQL中要使用的标签
- 动态SQL中对null值的处理
- 对超大字符串及分页的处理
连接DB数据库的参数来自于Properties对象
在src目录下创建”XX.properties”文件(如db.properties),将要配置的内容以键值对的形式写入文件:
drivername=com.mysql.jdbc.Driver url=jdbc:mysql:///mybatis username=root password=951029
修改mybatis-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 resource="db.properties"/> <--!加上配置路径--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="url" value="${url}" /> <property name="driver" value="${drivername}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="orm/UserinfoMapper.xml"/> </mappers> </configuration>
<resultMap>
标签
如果数据表中的字段名称和java实体类中属性名称不一致时可使用<resultMap>
,我试了一下查询时好用,但插入时就出问题了
更改UserinfoMapper.xml中<result>
中property和column不一样,实体类中也得相应更改
<result column="password" property="passwordhy" jdbcType="VARCHAR" />
<sql>
标签
目的:解决sql语句重复使用
<mapper namespace="orm.UserinfoMapper">
<sql id="userinfoField">id,name,password</sql>
<select id="getUserinfoAll" resultType="map">
select
<include refid="userinfoField"/>
form
userinfo
</select>
</mapper>
将SQL语句作为字符串变量传入
在userinfoMapper.xml文件中
<select id="">
select
id,username,password
from
userinfo where id=#{id} order
by ${orderSql}
</select>
java类
HashMap mapParam=new HashMap();
mapParam.put("id",5);
mapParam.put("orderSql","id desc");
......//创建sqlSession
List <Map>listuserInfo=sqlSession.selectList('getUserinfo",mapParam); //传递mapParam参数
for(......) {
//遍历操作
}
插入null值的处理办法(2种方法)
jdbcType(第1种)
在映射配置文件userinfoMapping.xml文件中
<insert ......>
insert into userinfo(id,username,password)
values(#{id,jdbcType=INTEGER},#{username,jdbcType=VARCHAR},#{password,jdbcType=VARCHAR)
</insert>
这里在#{}格式中加入了数据类型声明,这样可以明确地告诉MyBatis框架如果遇到null值该如何处理。
<if>
(第2种)
在映射配置文件userinfoMapping.xml文件中
<insert ......>
<if test="password!=null">
insert into userinfo(id,username,password)
values(#id{id},#{username},#{password})
</if>
<if test="password==null">
insert into userinfo(id,username)
values(#{id},#{username})
</insert>
<choose>
标签
<choose>
标签的作用是在众多的条件中选择一个条件,类似于switch标签,在配置映射文件中使用
<select .....>
select * from where 1=1
<choose>
<when test="username!=null"> and username like '%'||#{username}||'%'</when>
<when>......</when>
<otherwise>and password=123</otherwise>
</choose>
</select>
<set>
标签
<set>
标签可以用在update语句中,用于动态指定要更新的列,在配置文件中使用
<update ......>
update userinfo
<set>
<if test="username!=null">username=#{username},</if>
<if .....>......</if>
<if test="password!=null">password=#{password},</if>
</set>
<foreach>
标签
foreach标签有循环功能,可以用来生成有规律的SQL语句。
foreach标签主要的属性有item、index、collection、open、separator和close。
item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中的位置,open表示语句以什么开始,separator表示在每次迭代之间以什么符号作为分隔符,close表示该语句以什么结束。
<select ......>
<foreach collection="criteria.criteria" item="criterion" open="(" close=")" separator="," >
#{criterion}
</foreach>
</select>
分页
SqlSession sqlSession=GetSqlSession.getSession();
//RowBounds(a,b),a代表从第a个记录开始(0为第一个),往后移动b个位置
List<Userinfo> listMap=sqlSession.selectList("selectByExample",null,new RowBounds(2,4));
for (int i = 0; i < listMap.size(); i++) {
Userinfo e=listMap.get(i);
System.out.println(e.getId());
}