一、原生jdbc程序中问题总结
1.1、jdbc程序
使用jdbc查询mysql数据库中用户表中的记录:
package com.shuai;
import java.sql.*;
public class JdbcTest {
public static void main(String[] args) throws SQLException {
Connection conn=null;
//预编译的statement, 提高性能
PreparedStatement ps=null;
//结果集
ResultSet rs=null;
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&userSSL=false&serverTimezone=GMT%2B8","root","root");
//定义sql语句
String sql="select * from user where userName=?";
//获取预处理statement
ps=conn.prepareStatement(sql);
//设置参数
ps.setString(1, "guai");
//执行sql获取结果
rs=ps.executeQuery();
while(rs.next()) {
System.out.println(rs.getString(1)+rs.getString(2)+rs.getString(3)+rs.getString(4));
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
if(rs!=null) {
rs.close();
}
if(ps!=null) {
ps.close();
}
if(conn!=null) {
conn.close();
}
}
}
}
1.2、问题总结
1、数据库连接使用时创建,不使用时释放,对数据库频繁连接开启和关闭,影响数据库性能。
解决方法:使用数据库连接池管理数据库连接
2、将sql语句硬编码到java代码中,如果要修改sql语句,需要重新编译java代码,不利于维护。
解决方法:将sql语句配置在xml配置文件中,即使sql变化,不需对java代码进行重新编译。
3、在preparestatement中设置参数时,对占位符位置和参数设置都是硬编码在java代码中,不利于维护。
解决方法:将sql语句和参数全配置到xml中
4、从resultset中便利结果集是,参在硬编码,不利于维护。
解决方法:将结果集映射成java对象
硬编码:将代码写死
二、mybatis框架
2.1、针对jdbc编程中存在的问题,我们引入mybatis框架。那么什么是mybatis呢?
mybatis是一个优秀的持久层框架,用于简化程序员对数据库的操作、维护。mybatis通过映射的方式,将向preparestatement中的输入参数进行映射,并将查询结果集灵活映射成java对象。
2.2、mybatis框架详解:
三、入门程序
3.1、需求:
根据用户id查询用户信息
模糊查询
增删改记录
3.2、创建java程序,并导入jar包
在项目目录下新建lib文件夹并将jar包复制到该目录下,然后选中所有jiar包右击buildpath点击add
3.3、创建日志文件log4j.properties
创建config文件夹并在该文件夹下创建日志文件log4j.properties,并复制以下内容到日志文件中:
# Global logging configuration
#在开发环境下日志级别要设置成debug,生产环境设置成info或error
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 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
3.4、配置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>
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,由mybatis管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理 -->
<dataSource type="POOLED">
<!-- jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&userSSL=false&serverTimezone=GMT%2B8","root","root"); -->
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useSSL=FALSE"/>
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml" />
</mappers>
</configuration>
3.5、创建实体类
package com.shuai.po;
/**
*
* @author guai
*
*/
public class User {
private int id;
private String userName;
private int sex;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", sex=" + sex + ", address=" + address + "]";
}
}
3.6、配置映射文件User.xml(用于配置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,称为statement的id
将来sql语句封装到mapperStatement对象中,所以将id称为statement的id
#{id}表示占位符 id表示输入的参数,参数名称为id,如果输入参数是简单类型,#{}中的参数名称可以任意
${}:表示拼接字符串,将接收到的参数内容拼接到sql中
使用%{}容易被sql注入攻击
${value}:接受输入的参数,如果传入类型是简单类型,${}中只能使用value
paramterType:指定输入参数类型
resultType:指出sql输出结果映射的java对象类型,select指定resultType表示将单条记录映射成的java对象
-->
<select id="selectById" parameterType="int" resultType="com.shuai.po.User">
select * from user where id=#{id}
</select>
<!-- 根据姓名模糊查询用户 -->
<select id="selectByName" parameterType="java.lang.String" resultType="com.shuai.po.User">
select * from user where userName like '%${value}%'
</select>
<!-- 添加用户
parameterType:指定输入参数类型为pojo
#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过ognl获取对象的属性值
selectKey:获取主键
select LAST_INSERT_ID():sql函数获取插入记录的id
keyProperty:将查到的主键信息设置到指定的User属性中
order:指定执行顺序
resultType:指定查询结果类型
-->
<insert id="insertUser" parameterType="com.shuai.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
insert into user(id,userName,sex,address) value(#{id},#{userName},#{sex},#{address})
</insert>
<!--
#{id}:从参数uer对象中获取属性
-->
<update id="updateUser" parameterType="com.shuai.po.User">
update user set userName=#{userName},sex=#{sex},address=#{address} where id=#{id}
</update>
<delete id="delUser" parameterType="int">
delete from user where id=#{id}
</delete>
</mapper>
3.7程序编写
该程序使用junit测试
package com.shuai.mybatis;
/**
* 入门程序
* @author guai
*
*/
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import com.shuai.po.User;
public class MyBatisTest1 {
//根据id查询用户信息,得到一条记录
//@Test
public void selectUserTest() throws IOException {
//mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream=Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSessioin
SqlSession sqlSession=sqlSessionFactory.openSession();
//通过SqlSession操作数据库
//statemenet:映射文件中statement的id,等于namespace=statement的id
//parament:指定和映射文件中所匹配的paramterType类型的参数
//sqlSession.sqlectOne结果是与映射文件中所匹配的resultType类型的对象
//selectOne查询一条记录进行映射
//User user=sqlSession.selectOne("test.selectById", 1);
//selectLIst查询多条记录进行映射
List<User> users=sqlSession.selectList("test.selectByName", "gua");
System.out.println(users);
//释放资源
sqlSession.close();
}
//@Test
public void insertTest() throws IOException {
//mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream=Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSessioin
SqlSession sqlSession=sqlSessionFactory.openSession();
//通过SqlSession操作数据库
//statemenet:映射文件中statement的id,等于namespace=statement的id
//parament:指定和映射文件中所匹配的paramterType类型的参数
//sqlSession.sqlectOne结果是与映射文件中所匹配的resultType类型的对象
User user=new User();
user.setUserName("shuai1");
user.setSex(1);
user.setAddress("henan");
sqlSession.insert("test.insertUser",user);
//提交事务
sqlSession.commit();
System.out.println("user:"+user);
//释放资源
sqlSession.close();
}
//@Test
public void updateUser() throws IOException {
//1、获取mybatis配置文件流
InputStream is=Resources.getResourceAsStream("SqlMapConfig.xml");
//2、获取会话工厂
SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(is);
//3、从工厂中获取一个sqlsession会话
SqlSession ss=sf.openSession();
//4、通过sqlsession执行sql操作
//4.1、获取user对象
User user=new User();
user.setId(12);
user.setUserName("shuai1");
user.setSex(0);
user.setAddress("henan");
ss.update("test.updateUser", user);
ss.commit();
//5、释放资源
ss.close();
}
@Test
public void delUser() throws IOException {
//1、获取mybatis映射文件流
InputStream is=Resources.getResourceAsStream("SqlMapConfig.xml");
//2、获取会话工厂
SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(is);
//3、通过会话工厂获取会话
SqlSession ss=sf.openSession();
//4、通过会话执行sql操作
ss.delete("test.delUser",12);
ss.commit();
//5、释放资源
ss.close();
}
}
3.8、总结
3.8.1、#{}与${}
#{}:表示占位符,#{}接收参数时可以是简单类型,pojo(javabean简单但对象),hashmap,当接收简单类型时,#{}中可以是value或其他名称,当接收pojo对象值时,通过ognl读取对象属性值。
(ognl:一种强大的表达式语言,可以存取对象的任意属性)
表
示
s
q
l
拼
接
(
容
易
遭
到
s
q
l
注
入
攻
击
)
,
接
收
参
数
时
,
可
以
简
单
类
型
,
p
o
j
o
、
h
a
s
h
m
a
p
,
接
受
简
单
类
型
时
,
{}表示sql拼接(容易遭到sql注入攻击),接收参数时,可以简单类型,pojo、hashmap,接受简单类型时,
表示sql拼接(容易遭到sql注入攻击),接收参数时,可以简单类型,pojo、hashmap,接受简单类型时,{}内只能写value