MyBatis入门程序案例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34598667/article/details/83832715

mybatis下载

mybaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releases。 可从该地址下载mybatis最新框架。
下载之后解压缩:
在这里插入图片描述


案例需求

1 根据用户id查询y一个用户信息
2 根据用户名模糊查询用户信息列表
3 添加用户信息
4 修改用户信息
5 删除用户信息


MyBatis入门程序配置

1)新建数据库mybatis

在这里插入图片描述

2)新建表user

CREATE TABLE `NewTable` (
`id`  int(4) NOT NULL AUTO_INCREMENT ,
`name`  varchar(7) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
PRIMARY KEY (`id`)
)ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci;

3)新建项目mabatis_demo01(以web项目为例)

在这里插入图片描述

4)导入jar包

工程所需加入的Jar包有mybatis核心包、依赖包和mysql数据驱动包。
在这里插入图片描述

5)在工程下新建一个源码包config,并在其中创建一个日志记录文件–log4j.properties

在这里插入图片描述

log4j.properties文件:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

mybatis默认使用log4j作为输出日志信息。

6)在config源码包中新建MyBatis的配置文件SqlMapConfig.xml

在这里插入图片描述

SqlMapConfig.xml是mybatis的核心配置文件,我们来直接配置数据源以及事务管理

<?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>
    <!-- 和spring整合后environments配置将废除 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>
</configuration>

注意:等后面mybatis和Spring两个框架整合之后,environments的配置将被废除。

7)创建一个实体类User

在包com.oak.domain下新建实体类User
在这里插入图片描述
User类内容为:

public class User {
	//user的id
	private Integer id;
	//user的name
	private String name;
	public User() {
		super();
	}
	public User(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + "]";
	}
}

8)在源码包config下新建一个包sqlmap,在其中创建映射文件user.xml

在该包内新建user.xml,此文件即sql映射文件,文件中配置了操作数据库的sql语句,此文件需要在SqlMapConfig.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="test">

</mapper>

namespace:即命名空间,其用于隔离sql语句(即不同sql映射文件中的两个相同id的sql语句如何来区分),这是当前的作用,后面会讲另一层非常重要的作用。

9)加载映射文件。mybatis框架需要加载映射文件,将user.xml添加在SqlMapConfig.xml中

在SqlMapConfig.xml配置文件中添加如下配置信息

<mappers>
    <!-- resource是基于classpath(源码包)来查找的 -->
    <mapper resource="sqlmap/user.xml"/>
</mappers>

在这里插入图片描述

10)根据id查询用户信息

在user.xml映射文件中添加如下配置:

<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int" resultType="com.oak.domain.User">
	select * from `user` where id=#{id};
</select>
  • < select>标签用于定义查询语句,相应的还有增删改

  • parameterType:参数的数据类型,即定义输入到sql中的映射类型。

  • resultType:结果的数据类型,如果是pojo则应该给出全路径。

  • #{id}表示使用PreparedStatement设置占位符号并将输入变量id传到sql中。说白点,#{}作用就是占位符,相当于JDBC中的?。

11)在com.oak.test包中新建MyBatisTest类,在类中新建测试方法:

  @Test
  public void findUserById() throws IOException {
      // 第一步,创建SqlSessionFactoryBuilder对象
      SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
      // 第二步,加载配置文件
      InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
      // 第三步,创建SqlSessionFactory对象
      SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
      // 第四步,创建SqlSession对象
      SqlSession sqlSession = sqlSessionFactory.openSession();
      // 第五步,使用SqlSession对象执行查询,得到User对象
      // 第一个参数:执行查询的StatementId
      User user = sqlSession.selectOne("findUserById", 1);
      // 第六步,打印结果
      System.out.println(user);
      // 第七步,释放资源,每一个sqlSession就是一个连接
      sqlSession.close();
  }

以上步骤过于繁琐,而一般来讲工厂对象一般在实际开发是单例的,并不需要频繁地创建,所以我们在此给SqlSessionFactory定义为单例:

public class MyBatisTest {
	// 工厂对象一般在我们的系统中是单例的
	private SqlSessionFactory sqlSessionFactory=null;
	/**
	 * Junit中的基本注解,不是AOP中的那个,
	 * 表示在任意使用@Test注解标注的public void方法执行之前执行
	 * @throws IOException 
	 */
	@Before
	public void init() throws IOException{
		// 第一步,创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 第二步,加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 第三步,创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
	}
	@Test
    public void findUserById() throws IOException {
        // 第四步,创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 第五步,使用SqlSession对象执行查询,得到User对象
        // 第一个参数:执行查询的StatementId
        User user = sqlSession.selectOne("findUserById", 1);
        // 第六步,打印结果
        System.out.println(user);
        // 第七步,释放资源,每一个sqlSession就是一个连接
        sqlSession.close();
    }
}

执行测试:
在这里插入图片描述

12)根据用户名称模糊查询用户信息列表

在user.xml中添加如下配置:
<!-- 根据名称模糊查询用户信息列表 -->
<select id="findUserByName" parameterType="String" resultType="com.oak.domain.User">
	select * from `user` where name like #{name}
</select>

如果查询结果返回的是List集合,那么resultType只需要设置为List集合中的一个元素的数据类型即可。

在测试类中测试:
@Test 
public void findUserByName(){
	//创建SqlSession对象
	SqlSession sqlSession=sqlSessionFactory.openSession();
	//执行查询
	List<User> list=sqlSession.selectList("findUserByName","%s%");
	System.out.println(list);
	sqlSession.close();
}

运行测试,查看结果:
在这里插入图片描述

使用${value}字符串拼接指令完成此任务

修改xml中的sql为:

<!-- 根据名称模糊查询用户信息列表 -->
<select id="findUserByName" parameterType="String" resultType="com.oak.domain.User">
	select * from `user` where name like '${value}'
</select>

$ {value}表示使用参数将$ {value}替换,做字符串的拼接,${}为字符串拼接指令。注意:如果是取简单数据类型的参数,括号中的值必须为value。
直接运行上述测试方法:
在这里插入图片描述
很明显这种方式在实际开发中是不建议使用的,因为无法防止SQL注入,建议使用#{ }。


小结

1)#{}和${}

#{}:表示一个占位符号,可以很好地去避免sql注入。其原理是将占位符位置的整个参数和sql语句两部分提交给数据库,数据库去执行sql语句,去表中匹配所有的记录是否和整个参数是否一致。
#{}要获取输入参数的值:

  • 如果输入参数是简单数据类型,则#{}中可以写value或其它名称。

  • 如果输入参数是pojo对象类型,则#{}可通过OGNL方式去获取,表达式就是属性.属性.属性…方式。

$ {}:表示一个sql拼接符号,其原理是在向数据库发出sql之前去拼接好sql再提交给数
据库执行。
${}要获取输入参数的值:

  • 如果输入参数是简单数据类型,则${}中只能写value。

  • 如果输入参数是pojo对象类型,则${}可通过OGNL方式去获取,表达式就是属性.属性.属性…方式。

一般情况下建议使用#{},特殊情况下必须要用${},比如:

  • 动态拼接sql中动态组成排序字段,要通过$ {}将排序字段传入sql中。

  • 动态拼接sql中动态组成表名,要通过$ {}将表名传入sql中。

2)parameterType和resultType

parameterType:指定输入参数类型,mybatis通过ognl方式从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。

3)selectOne()和selectList()方法

selectOne:查询一条记录,如果使用selectOne查询多条记录则抛出异常
selectList:可以查询一条或多条记录。


13)添加一条用户信息

在xml配置文件中添加配置:

<!-- 添加一条信息 -->
<insert id="addUser" parameterType="com.oak.domain.User">
		insert into `user` values(null,#{name})
</insert>

如果输入参数类型是po,那么#{}中的名称就是po类中的属性,不能随便定义。
测试类中测试

@Test
public void addUser(){
	//创建SqlSession对象
	SqlSession sqlSession=sqlSessionFactory.openSession();
	sqlSession.insert("addUser", new User(null, "ww"));
	sqlSession.close();
}

查看控制台:
在这里插入图片描述
查看数据库:
在这里插入图片描述
虽然发出了sql语句,但是事务并没将其提交,而是回滚了。故User对象是无法插入到数据库user表中的。
应该在执行之后进行事务提交。修改测试方法为:

@Test
public void addUser(){
	//创建SqlSession对象
	SqlSession sqlSession=sqlSessionFactory.openSession();
	sqlSession.insert("addUser", new User(null, "ww"));
	sqlSession.commit();
	sqlSession.close();
}

查看控制台:
在这里插入图片描述
查看数据库:
在这里插入图片描述
事务已提交,可发现数据库user表中插入一条记录。

14)MySQL自增主键返回

想要得到MySQL数据库给我们生成的主键id,即获取主键。
这里要用到MySQL数据库中的一个函数:

  • LAST_INSERT_ID():返回auto_increment自增列新记录id值。该函数是在当前事务下取到你最后生成的id值,而我们应知道查询操作是没有开启事务的,增删改操作是需要开启事务的。

为了获取自动主键,更改user.xml中的addUser为:

<!-- 添加一条信息 返回自动增长主键 -->
<insert id="addUser" parameterType="com.oak.domain.User">
	<selectKey keyProperty="id" resultType="int" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
	insert into `user` values(null,#{name})
</insert>
  • keyProperty:返回的主键存储在po中的哪个属性(即其对应po的主键属性)。获取主键,实际上是将主键取出来之后封装到了po的主键属性当中。

  • resultType:返回的主键是什么类型(即其对应pojo的主键的数据类型)。

  • order:selectKey的执行顺序,是相对于insert语句来说的,由于mysql的自增原理,执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为AFTER。

在测试类中修改测试方法为:

@Test
public void addUser(){
	//创建SqlSession对象
	SqlSession sqlSession=sqlSessionFactory.openSession();
	//只给name赋值
	User user=new User(null, "zl");
	sqlSession.insert("addUser", user);
	System.out.println("或者自动增长主键:"+user.getId());
	sqlSession.commit();
	sqlSession.close();
}

查看测试结果:
在这里插入图片描述
查看数据库:
在这里插入图片描述

15)删除信息

在user.xml中添加

<!-- 删除用户 -->
<delete id="deleteUser" parameterType="int">
	delete from `user` where id=#{id}
</delete>

在测试类中测试:

@Test
public void delUser(){
	//创建SqlSession对象
	SqlSession sqlSession=sqlSessionFactory.openSession();
	sqlSession.delete("deleteUser",1);
	sqlSession.commit();
	sqlSession.close();
}

16)修改信息

在user.xml中添加修改:

<!-- 修改信息 -->
<update id="updateUser" parameterType="com.oak.domain.User">
	update `user` set name=#{name} where id=#{id}
</update>

测试:

@Test
public void updateUser(){
	//创建SqlSession对象
	SqlSession sqlSession=sqlSessionFactory.openSession();
	sqlSession.update("updateUser",new User(2, "李四"));
	sqlSession.commit();
	sqlSession.close();
}

MyBatis解决了JDBC编程的问题

  • 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
    解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库连接。

  • Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
    解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

  • 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
    解决: MyBatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

  • 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
    解决: MyBatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

猜你喜欢

转载自blog.csdn.net/qq_34598667/article/details/83832715