重点:与hibernate不同的时,在mybatis中,持久化类也就是对应的po对象,对应的不在是表,而是返回的类型。
入门:核心的配置文件:sqlMapConfig.xml 和对应的po对应的配置文件:User.xml(以user为例).
配置示例:
<?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">//DTD约束
<configuration>
//这个标签是为了配置别名,方便使用的。
<typeAliases>
<typeAlias type="cn.itcast.mybatis.domain.User" alias="User"/>
//为user对象配置一个别名user,这样在User.xml中就可以直接写User即可。
</typeAliases>
//篇日志数据库的相关信息
<environments default="development">
<!-- 连接数据库的开发环境 -->
<environment id="development">
<transactionManager type="JDBC"/> //type代表方式使用jdbc作为底层操作
<dataSource type="POOLED"> //此处POOLED代表使用缓存
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!-- 连接数据库的部署环境同上 -->
<environment id="product">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdbproduct?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
//在mappers中导入已经建好的po对象的配置文件,注意这里访问的是文件resource,所以要用/不用.
<mappers>
<mapper resource="cn/itcast/mybatis/domain/User.xml"/>
</mappers>
</configuration>
po对象对应的映射文件示例:其实mybatis中最核心的就是po对象的映射文件配置,掌握了这个配置也就掌握了mybatis的使用。
<?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.itcast.mybatis.domain.User">*****::注意此处定义的是命名空间
*****在java类中进行操作的时候,需要的是命名空间.对应的操作的标签的id来实现。这里定义的和pojo全路径名虽然一样,但是与那个完全是两个概念,
这里的namespace所指的只是命名空间,与其他无关。
<sql id="cols">
id,name,age,address
</sql>
<!-- 简化操作,比如一个po类中所含有的字段有60多个,每次查询时重复书写很麻烦,为了避免这种情况,
可以使用sql标签,将字段定义在sql标签中,在使用时使用<include refid="">引号中填写对应的sql标签的id即可。
-->
<sql id="createcols">
#{id},#{name},#{age},#{address}
</sql>
<!-- 查询所有记录,将sql语句定义到了select标签中。sql语句由程序员来书写 -->
<select id="selectList" resultType="User">
<!-- id是唯一的存在,是需要在程序中动态传入的,这样mybatis才能识别调用的是哪一个。
这里的id的名称自定义,尽量定义成贴切的名称,方便使用。
-->
select <include refid="cols"/> from user_c
<!-- 而在配置文件中可以在sql语句中插入include标签,
利用refid将对应id的sql标签的内容动态的插入到sql语句中。
-->
</select>
<!-- 查询一条 ,查询一条时需要传入参数,所以要写parameterType=“参数类型”
而返回的结果,用resultType=”返回的结果类型“,这里就是和hibernate最大的区别。
hibernate的映射文件对应的是表和pojo类。而mybatis对应的是结果集类型。
-->
<select id="get" parameterType="string" resultType="cn.itcast.mybatis.domain.User">
SELECT <include refid="cols"/> FROM user_c WHERE id=#{id}
<!--动态的传入sql标签中定义的内容-->
</select>
<!-- 按条件查询 -->
<select id="find" parameterType="cn.itcast.mybatis.domain.User" resultType="cn.itcast.mybatis.domain.User">
select <include refid="cols"/> from user_c
<where>
<if test="name!=null">
and name like #{name}
</if>
<if test="address!=null">
and address=#{address}
</if>
</where>
<!--利用where标签可以解决如果某个传入的参数为null时,会出现查不出来任何东西的问题。
并且可以在之中嵌套使用if标签,test中跟表达式,进行一些逻辑判断。
-->
</select>
<!-- 新增记录 -->
<insert id="create" parameterType="cn.itcast.mybatis.domain.User">
insert into user_c
(id,name,age,address)
values( <include refid="createcols"/> )
</insert>
<!-- 修改记录 -->
<update id="update" parameterType="cn.itcast.mybatis.domain.User">
update user_c
<set>
<if test="name!=null">
name=#{name},
</if>
<if test="age!=null">
age=#{age},
</if>
<if test="address!=null">
address=#{address},
</if>
</set>
where id=#{id}
<!--set标签,能够解自动去掉最后一个参数后的逗号,的作用。避免拼串操作的错误-->
</update>
<!-- 删除记录 -->
<delete id="delete" parameterType="string">
delete from user_c where id=#{id}
</delete>
</mapper>
最java中代码的实现:
public class TestMybatis {
//Session工厂
SqlSessionFactory sqlSessionFactory;
@Before
public void initFactory() throws IOException{
String resource = "sqlMapConfig.xml"; //配置文件
InputStream in = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //获得sqlSessionFactory
}
@Test //测试取得所有记录
public void testListAll(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
List<User> users = session.selectList("cn.itcast.mybatis.domain.User.listAll"); //命名空间+方法名
System.out.println("总记录个数:"+users.size());
}
@Test //获取USER对象
public void testGet(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
User u = session.selectOne("cn.itcast.mybatis.domain.User.get","3"); //获取一条
System.out.println("获得的对象:"+u);
}
@Test //按条件查询
public void testFind(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
User u = new User();
u.setName("%g%");
u.setAddress("江陵");
List<User> users = session.selectList("cn.itcast.mybatis.domain.User.find", u);
System.out.println("查找到的记录个数:"+users.size());
}
@Test //新增记录
public void testCreate(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
User u = new User();
u.setId(UUID.randomUUID().toString()); //产生UUID主键
u.setName("jack");
u.setAge(22);
u.setAddress("beijing");
int i = session.insert("cn.itcast.mybatis.domain.User.create", u);
session.commit();
System.out.println("影响条数:"+i);
}
@Test //修改记录
public void testUpdate(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
//User u = session.selectOne("cn.itcast.mybatis.domain.User.get","100");
User u = new User();
u.setId("100");
u.setName("rosexxx");
int i = session.update("cn.itcast.mybatis.domain.User.update", u);
session.commit();
System.out.println("影响条数:"+i);
}
@Test //删除
public void testDelete(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
int i = session.delete("cn.itcast.mybatis.domain.User.delete", "2");
session.commit();
System.out.println("影响条数:"+i);
}
}
public class TestMybatis {
//mybatis的Session工厂
SqlSessionFactory sqlSessionFactory;
@Before
public void initFactory() throws IOException{
String resource = "sqlMapConfig.xml"; //配置文件
InputStream in = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //加载配置文件,获得sqlSessionFactory
}
@Test //测试取得所有记录
public void testListAll(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
List<User> users = session.selectList("cn.itcast.mybatis.domain.User.listAll"); //命名空间+方法名
System.out.println("总记录个数:"+users.size());
}
@Test //获取USER对象
public void testGet(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
User u = session.selectOne("cn.itcast.mybatis.domain.User.get","3"); //获取一条,第二个参数即对应配置中的id
System.out.println("获得的对象:"+u);
}
@Test //按条件查询
public void testFind(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
User u = new User();
u.setName("%g%");
u.setAddress("江陵");
List<User> users = session.selectList("cn.itcast.mybatis.domain.User.find", u);
System.out.println("查找到的记录个数:"+users.size());
}
@Test //新增记录
public void testCreate(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
User u = new User();
u.setId(UUID.randomUUID().toString()); //产生UUID主键
u.setName("jack");
u.setAge(22);
u.setAddress("beijing");
int i = session.insert("cn.itcast.mybatis.domain.User.create", u);
session.commit();
System.out.println("影响条数:"+i);
}
@Test //修改记录
public void testUpdate(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
//User u = session.selectOne("cn.itcast.mybatis.domain.User.get","100");
User u = new User();
u.setId("100");
u.setName("rosexxx");
int i = session.update("cn.itcast.mybatis.domain.User.update", u);
session.commit();
System.out.println("影响条数:"+i);
}
@Test //删除
public void testDelete(){
SqlSession session = sqlSessionFactory.openSession(); //获得SqlSession
int i = session.delete("cn.itcast.mybatis.domain.User.delete", "2");
session.commit();
System.out.println("影响条数:"+i);
}
}
生命周期:
SqlSessionFactoryBuilder
这个类可以被实例化,使用和丢弃。一旦你创建了SqlSessionFactory后,这个类就不需要存在了。因此SqlSessionFactoryBuilder实例的最佳范围是方法范围(也就是本地方法变量)。SqlSessionFactory
一旦被创建,SqlSessionFactory实例应该在你的应用程序执行期间都存在。没有理由来处理或重新创建它。使用SqlSessionFactory的最佳实践是在应用程序运行期间不要重复创建多次。因此SqlSessionFactory的最佳范围是应用范围。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。然而这两种方法都不认为是最佳实践。考虑依赖注入容器,比如Google Guice或Spring。这样的框架允许你创建支持程序来管理单例SqlSessionFactory的生命周期。
SqlSession
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet架构中的HttpSession。
基于收到的HTTP请求,你可以打开了一个SqlSession,然后返回响应,就可以关闭它了。关闭Session很重要,你应该确保使用finally块来关闭它。下面的示例就是一个确保SqlSession关闭的基本模式:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
映射器实例
映射器是你创建绑定映射语句的接口。映射器接口的实例可以从SqlSession中获得。那么从技术上来说,当被请求时,任意映射器实例的最宽范围和SqlSession是相同的。然而,映射器实例的最佳范围是方法范围。也就是说,它们应该在使用它们的方法中被请求,然后就抛弃掉。
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
} finally {
session.close();
}