上一个小demo只是演示了mybatis的执行过程是怎样的,我们先来回顾一下:
首先是写配置文件:
sqlMapConfig.xml中定义数据源连接池的属性,用来与数据库获取连接;
接下来写usermapper.xml,来替换之前jdbc中写死的sql,其中有输入映射与输出映射;
这时候我们需要一个pojo来作为其中的输入或输出等,其属性与数据库中保持一致;
最后在test中要首先获取配置文件的输入流,根据它获取一个sqlSessionFactory,再用sqlSessionFactory创建sqlSession来操作数据库
那么这次我们来完成基本的增删改查操作,其中的一些知识点我都在代码注释中写了,我习惯这样写,这样能帮助我理清思路,知道程序的流程以及需要注意的点
sqlMapConfig.xml不变
mybatis主要就是对于这个sql配置文件的编写:
<?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" >
<!-- namespace命名空间,作用是对sql进行分类化管理,理解sql隔离
使用mapper代理的方法开发
namespace有很重要的作用
-->
<mapper namespace="test">
<!-- 在映射文件中配置很多sql语句 -->
<!-- 通过select执行查询
id:用来表示文件中的sql,将sql语句封装到mappedstatement对象中,所以id其实是statement的id
parameterType:指定输入参数类型,id是int型
#{}表示一个占位符
#{id}表示id是接受的输入参数,名字是id,如果输入参数是简单类型,#{}中的参数名可以任意,可以是value或者其他名称
resultType:结果返回类型所映射的类,是单条记录所映射的对象类型 -->
<!-- 通过id查询用户 -->
<select id="findUserById" parameterType="int"
resultType="com.ddd.mybatis.pojo.User">
SELECT * FROM USER WHERE id=#{id}
</select>
<!-- 通过名字查询用户 可能会查询出多条记录
resultType:结果返回类型所映射的类,是单条记录所映射的对象类型 所以这里还是用user而不是list
使用${}是sql拼接,这是将接收的参数不加任何修饰的拼接成sql
但这种可能会引起sql注入,也就是用户可能会输入一些字符串, 让查询条件恒真,例如
SELECT * FROM USER WHERE username LIKE '%' OR 1=1 OR '%' 这样就能查询所有数据
-->
<select id="findUserByName" parameterType="java.lang.String"
resultType="com.ddd.mybatis.pojo.User">
SELECT * FROM USER WHERE username LIKE '%${value}%'
</select>
<!-- 添加用户 parameterType为pojo,来接受一个用户的信息
其中id可以省略,因为id是自增的
#{}中指定的是pojo的属性名,接受pojo的属性值,mybatis通过ONGL获取对象的属性值
-->
<insert id="insertUser" parameterType="com.ddd.mybatis.pojo.User">
<!-- 用来返回主键,返回到user中去
SELECT LAST_INSERT_ID():查询刚刚插入的数据的主键id,但是只适用于自增型
keyProperty:将查询到主键值中的parameterType指定的对象的那个属性
order="AFTER":表示SELECT LAST_INSERT_ID()是在insert执行之后
resultType:执行查询的结果返回类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
<!-- 非自增主键的返回
首先使用uuid()生成主键,将其设置到user的对象id属性中
在insert执行时从user对象中取出id的属性值返回
但是在insert语句中必须添加id这个属性,因为它不是自增的,不能省略
<selectKey keyProperty="id" order="BEFORE"
resultType="java.lang.String"> SELECT UUID()
</selectKey> -->
INSERT INTO USER(username,sex,birthday,address)
VALUES(#{username},#{sex},#{birthday},#{address})
</insert>
<!-- 根据id删除用户 -->
<delete id="deleteUserById" parameterType="java.lang.Integer">
DELETE FROM USER WHERE id=#{id}
</delete>
<!-- 根据id更新用户
需要传入用户的id,需要传入用户的更新信息
parameterType:指定的user对象就包括了这些信息
#{id}是从user中接收的id -->
<update id="updateUser" parameterType="com.ddd.mybatis.pojo.User">
UPDATE USER SET
username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
WHERE id=#{id}
</update>
</mapper>
<!--
tips:
1.#{}和${}
#{}表示一个占位符,#{}接收参数可以是简单类型,例如pojo.hashmap等,如果是简单类型#{}中可以写成value或者名称
${}表示一个拼接符,会引起sql注入,${}接收参数也可以是简单类型,如果是简单类型${}中只能写成value
#{}${}接收pojo时使用OGNL来读取pojo的属性
-->
我们再看看测试代码是怎样的:
package com.ddd.mybatis.first;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Date;
import java.util.List;
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 org.junit.Test;
import com.ddd.mybatis.pojo.User;
/**
* 测试mybatisdemo
* @author Dan
*
*/
public class MybatisFirst {
//根据id查询用户信息得到一条结果记录
@Test
public void findUserByIdTest() throws IOException{
//加载mybatis文件
String fileSource="SqlMapConfig.xml";
//获取文件流
InputStream inputStream=Resources.getResourceAsStream(fileSource);
//根据加载的配置文件信息创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//得到sqlsession
SqlSession sqlSession=sqlSessionFactory.openSession();
//sqlSession操作数据库
//第一个参数:映射文件中的statement的id:也就是namespace+"."+statement的id
//第二个参数:指定和映射文件中所匹配的parameterType类型的参数
//接受参数就是resultType中指定的对象类型
User u=sqlSession.selectOne("test.findUserById", 1);
System.out.println(u);
sqlSession.close();
}
@Test
public void findUserByNameTest() throws IOException{
//加载mybatis文件
String fileSource="SqlMapConfig.xml";
//获取文件流
InputStream inputStream=Resources.getResourceAsStream(fileSource);
//根据加载的配置文件信息创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//得到sqlsession
SqlSession sqlSession=sqlSessionFactory.openSession();
//sqlSession操作数据库
//这里list中的要指定是user,和resultType指定的类型保持一致,selectList表示查询多条记录
List<User> list=sqlSession.selectList("test.findUserByName", "小明");
for (User u:list) {
System.out.println(u);
}
sqlSession.close();
}
@Test
public void insertUserTest() throws IOException{
//加载mybatis文件
String fileSource="SqlMapConfig.xml";
//获取文件流
InputStream inputStream=Resources.getResourceAsStream(fileSource);
//根据加载的配置文件信息创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//得到sqlsession
SqlSession sqlSession=sqlSessionFactory.openSession();
User u=new User();
u.setUsername("大张伟");
u.setSex("男");
u.setBirthday(new Date());
u.setAddress("广州佛山");
sqlSession.insert("test.insertUser", u);
//这里需要提交,在使用spring后就不用提交了
sqlSession.commit();
/**1.
* 获取用户主键(自增主键的返回)
* mysql自增主键,执行insert提交之前会自动生成一个自增主键
* 自增主键可以通过mysql函数获取到:SELECT LAST_INSERT_ID(),但是这里是0
* System.out.println(u.getId());结果是0
* 所以应该在insert之后执行,所以要在mapper中设置返回主键
* 2.
* 获取用户主键(非自增的主键的返回)
* mysql的uuid()函数生成主键,需要修改表中id字段类型为String,长度35
* 先通过uuid()查询到主键,将主键输入到sql中
* 执行uuid()在insert语句之前执行
*/
//关闭会话
sqlSession.close();
}
//根据id删除一条用户记录
@Test
public void deleteUserByIdTest() throws IOException{
//加载mybatis文件
String fileSource="SqlMapConfig.xml";
//获取文件流
InputStream inputStream=Resources.getResourceAsStream(fileSource);
//根据加载的配置文件信息创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//得到sqlsession
SqlSession sqlSession=sqlSessionFactory.openSession();
//sqlSession操作数据库
sqlSession.delete("test.deleteUserById", 2);
sqlSession.commit();
sqlSession.close();
}
//更新用户
@Test
public void updateUserTest() throws IOException{
//加载mybatis文件
String fileSource="SqlMapConfig.xml";
//获取文件流
InputStream inputStream=Resources.getResourceAsStream(fileSource);
//根据加载的配置文件信息创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//得到sqlsession
SqlSession sqlSession=sqlSessionFactory.openSession();
//sqlSession操作数据库
User u=new User();
u.setId(3);
u.setUsername("huauhua");
u.setSex("女");
u.setBirthday(new Date());
u.setAddress("河南郑州");
sqlSession.update("test.updateUser", u);
sqlSession.commit();
sqlSession.close();
}
}
看看运行结果:
基本的增删改查就是这样啦,那么这里的parameterType中设置的user属性都是简单属性,那如果user中有了一个类属性又要怎么通过OGNL获取呢?
这里的SQLSession每次都一样,有什么办法可以解决呢?
事务每次都要提交,这未免也太麻烦!
别担心,spring会帮我们解决很多问题!
嗯!我要去学习!