Mybatis
原生态JDBC
原生态代码
public class JdbcTest {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
// 加载数据库驱动
try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 通过驱动管理类获取数据库连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "1234");
// 编写sql
String sql = "SELECT * FROM user WHERE username = ?";
// 获取预编译对象
preparedStatement = connection.prepareStatement(sql);
// 填充占位符parameterIndex从1开始
preparedStatement.setString(1, "张三");
// 执行sql语句
resultSet = preparedStatement.executeQuery();
// 遍历结果集
while(resultSet.next()){
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String sex = resultSet.getString("sex");
String address = resultSet.getString("address");
System.out.println(id+":"+username+":"+sex+":"+address);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement != null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
JDBC编程步骤
- 加载数据库驱动
- 创建并获取数据库连接Connection
- 创建一个Statement对象(预编译对象PreparedStatement)
- 编写sql语句
- 执行sql语句并获取结果
- 关闭连接,释放资源
JDBC问题
问题 | 解决方案 |
---|---|
频繁创建数据库连接,释放资源造成系统资源浪费,从而降低了系统性能 | 使用数据库连接池 |
SQL语句中存在硬编码,造成代码不易维护,如果SQL语句发生变更,需要重新编译Java代码 | 将SQL语句编写在XML文件中 |
使用preparedStatement的时候,填充占位符等存在硬编码问题,系统不容易维护 | 动态SQL |
对查询结果集解析也存在硬编码问题,比如从结果集取出数据的时候,系统不容易维护 | 将数据库的一条记录封装成一个POJO对象,解析就变得方便了,一条记录映射为一个对象 |
ORM对象关系映射
对象:JavaBean
关系:关系数据库
映射:对象和数据库中的表建立映射关系
对象关系映射指的是一个持久化类和一个表对应,对象对应表中一条记录,对象每个属性对应表的每个字段
特点:
- 提升了开发效率。ORM可以自动化完成对象(entity)和数据库(table)进行字段和属性的映射,简化DAO的开发
- ORM提供了对数据库的映射,就可以像操作对象一样操作数据库
Mybatis
基础知识
- mybatis是一个持久层框架(DAO)
- mybatis让程序员主要去编写SQL语句,通过mybatis提供的映射方式,灵活生成。
- mybatis可以将statement中的输入参数(占位符)自动进行输入映射,将查询的结果集灵活映射成Java对象。
运行原理图
Mybatis入门程序
package com.hpe.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
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.Before;
import org.junit.Test;
import com.hpe.mybatis.po.User;
public class UserTest {
SqlSessionFactory sqlSessionFactory;
@Before
public void createSqlSessionFactory() throws IOException{
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 1.创建会话工厂,传入mybatis的配置文件
sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
}
// 根据id查询用户信息
@Test
public void testSelectUserById() throws IOException {
// 2.通过会话工厂创键SqlSession(会话)
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3.通过sqlSession操作数据库执行SQL语句
// selectOne:代表查询一条记录
// statement:映射文件中statement的id(namespace.statementid)
// parameter:指定和映射文件中所匹配的ParameterType类型的参数
// 返回值:方法的返回结果与映射文件中resultType输出类型一致
User user = sqlSession.selectOne("user.selectUserById", 1);
System.out.println(user);
// 4.释放资源
sqlSession.close();
}
// 根据用户名模糊查询用户信息
@Test
public void testSelectUserByName() throws IOException {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 返回值是List集合:集合中的类型与映射文件中的resultType所指定的类型是一致的。
List<User> list = sqlSession.selectList("user.selectUserByName", "张");
System.out.println(list);
sqlSession.close();
}
// 添加用户数据
@Test
public void addUser() throws IOException {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 准备User
User user = new User("张大飞", new Date(), "2", "山东潍坊");
int result = sqlSession.insert("user.addUser", user);
sqlSession.commit();
// 获取用户主键
System.out.println(user.getId());
sqlSession.close();
}
// 删除用户信息
@Test
public void deleteUser() throws IOException {
SqlSession sqlSession = sqlSessionFactory.openSession();
int result = sqlSession.delete("user.deleteUser", 27);
System.out.println(result);
sqlSession.commit();
sqlSession.close();
}
// 用户更新信息
@Test
public void updateUser() throws IOException {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User("张大飞", new Date(), "1", "北京");
user.setId(26);
int result = sqlSession.update("user.updateUser", user);
System.out.println(result);
sqlSession.commit();
sqlSession.close();
}
}
Mybatis核心配置文件 sqlMapConfig.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>
<!-- mybatis的运行环境 -->
<!-- 将来和Spring整合之后,配置运行环境就废弃了 -->
<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="1234" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
</configuration>
UserMapper.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">
<!--namespace:命名空间,
作用:对SQL进行分类化管理(隔离SQL)
-->
<mapper namespace="user">
<!-- 在映射文件中可以配置很多SQL语句,不同的SQL语句有不同的标签
:select,updata,delete,insert
id:标识映射文件中的SQL,也可以称之为mapped statement
将来mybatis会把SQL语句封装到statement对象中
#{}:表示一个占位符,就相当于?
#{id}:其中的id表示接受的输入参数,id是参数名称
参数名称的要求:
1.如果输入参数是简单类型,参数名可以任意(可以是value可以是其他名称)
parameterType:指定输入参数类型
resultType:指定输出结果类型(执行SQL输出的结果所映射的Java对象类型)
-->
<!-- 1.根据用户id查询用户信息 -->
<select id="selectUserById" parameterType="int" resultType="com.hpe.mybatis.po.User">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 2.根据用户名模糊查询用户信息 -->
<!-- 返回结果可能是返回多条
resultType:指定的都是一条记录所映射的Java对象类型
'%${value}%'中${}:表示拼接字符串,使用这种方式会引起注入攻击
${value}:接受输入参数的内容,如果parameterType指定简单数据类型,那么${}中只能使用value
-->
<select id="selectUserByName" parameterType="java.lang.String" resultType="com.hpe.mybatis.po.User">
SELECT * FROM user WHERE username LIKE '%${value}%'
</select>
<!-- 3.添加用户 -->
<!-- parameterType:指定的类型是pojo,代表的是用户信息
#{}:中指定的是pojo的属性名,接受到的pojo对象的属性值是通过OGNL(对象导航语言)来读取和设置Java对象的属性值
调用对象的方法,遍历整个对象的结构图实现字段和属性的对应
注意:sql语句后面不能使用分号,否则不能正确解析SQL
-->
<insert id="addUser" parameterType="com.hpe.mybatis.po.User" >
<!-- 需求:将插入数据获得的主键,返回到User对象中identity得到的值赋值给id属性
方式一:SELECT LAST_INSERT_ID()只适用于自动增长列主键
方式二:SELECT @@IDENTITY同上
selectKey:获得新增的主键标签
1.keyProperty:将查询的主键设置到parameterType指定的属性上
2.order:执行顺寻(获取新增主键的顺寻),相对于insert语句来说的执行顺序
3.resultType:结果类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT @@IDENTITY
</selectKey>
INSERT INTO user(username,birthday,sex,address)
VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 4.根据用户id删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
DELETE FROM user WHERE id = #{id}
</delete>
<!-- 5.更新用户信息 -->
<!-- parameterType:指定的user对象,包含主键及要更新的信息
注意:id属性必须存在 -->
<update id="updateUser" parameterType="com.hpe.mybatis.po.User">
UPDATE user
SET username = #{username},birthday = #{birthday},sex = #{sex},address = #{address}
WHERE id = #{id}
</update>
</mapper>
sqlSessionFactoryBuilder
作用:创建sqlSessionFactory,可以使用工具类的方式来使用sqlSessionFactoryBuilder
sqlSessionFactory
- 是一个接口,由SqlSessionFactoryBuilder创建,接口中定义了一个openSession创建会话。
- 将来使用单例模式来管理。这样就可以避免每次操作都会创建
- 将来spring和mybatis整合之后,交给spring框架来进行管理sqlSessionFactory
SqlSession
- sqlSession是一个面向用户的接口,sqlSession这里定义了相关的数据操作,例如:
insert(),update(),delete,selectOne() - 由sqlSessionFactory 创建,每个线程都有自己的sqlSession实例,它是线程不安全的,无法实现
sqlSession实例的共享。使用局部变量。