环境准备: jdk+eclipse+maven
创建maven项目+配置pom.xml,加入数据库依赖
public class JdbcDemo { public static void main(String[] args) { Connection con = null; PreparedStatement psmt=null; ResultSet rs=null; try { // 1.加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 2.创建一个数据库连接对象 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/demo", "root", "root"); // 3.定义sql语句 String sql = "select*from 'user' where id=? "; // 4.创建Statement语句对象 psmt = con.prepareStatement(sql); // 5.设置参数 psmt.setInt(1, 10); // 6.执行 rs = psmt.executeQuery(); // 7.处理结果集 while(rs.next()){ System.out.println("用户Id:"+rs.getInt("id")+",用户名称:"+rs.getString("username")); } } catch (Exception e) { e.printStackTrace(); }finally{ // 8.释放资源 try{ if(rs != null) rs.close(); if(psmt != null) psmt.close(); if(con != null) con.close(); }catch(Exception e){ e.printStackTrace(); } } } }
频繁的创建连接对象和释放,容易造成系统资源的浪费,从而影响系统的性能,在企业中,可以通过使用连接池技术解决这个问题(Mybatis 内部提供连接池)
SQL语句的定义,参数设置,结果集处理存在问题
结果集处理存在重复代码,处理麻烦
是一个持久层框架,是对JDBC的封装;
通过xml或者注解进行配置,实现Java对象和SQL语句的对应关系
mapper代理开发步骤
1、要求mapper映射文件中的namespace属性值,必须是mapper代理接口的全限定名称
2、要求mapper映射文件中,sql语句标签的声明,与mapper接口方法的声明一致
2.1.要求sql语句的resultType属性指定的类型(如果返回值是一个集合,resultType指定的是集合中存放的类型),与mapper接口方法的返回值类型一致
2.2.要求sql语句的id属性值,与mapper接口的方法名称一致
2.3.要求sql语句的parameterType属性指定的类型,与mapper接口方法的参数类型一致
1.添加依赖(在pox.xml文件中加入)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itheima</groupId> <artifactId>mybatis-first</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>mybatis-first</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- mysql版本 --> <mysql.version>5.1.30</mysql.version> <!-- junit版本 --> <junit.version>4.12</junit.version> <!-- mybatis版本号 --> <mybatis.version>3.4.5</mybatis.version> <!-- log4j日志包版本 --> <slf4j.version>1.7.7</slf4j.version> <log4j.version>1.2.17</log4j.version> </properties> <dependencies> <!-- mysql数据库依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- mybatis核心包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- log4j日志包 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- junit依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> </project>
2.新建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> <!-- 运行环境配置 --> <!-- default:指定使用哪一个运行环境 --> <environments default="development"> <!-- id:唯一标识一个运行环境 --> <environment id="development"> <!-- 配置事务 --> <transactionManager type="JDBC" /> <!-- 数据源配置 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/demo" /> <property name="username" value="root" /> <property name="password" value="admin" /> </dataSource> </environment> </environments> </configuration>
3.新建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
4.新建用户实体类对象
public class User { private Integer id; // int(11) NOT NULL AUTO_INCREMENT, private String username; // varchar(32) NOT NULL COMMENT '用户名称', private Date birthday; // date DEFAULT NULL COMMENT '生日', private String sex; // char(1) DEFAULT NULL COMMENT '性别', private String address; // varchar(256) DEFAULT NULL COMMENT '地址', }+get/set方法+toString
5.编写mapper接口
public interface UserMapper { // 1.根据用户Id查询用户 User queryUserById(Integer id); // 2.新增一个用户 void insertUser(User user); }
6.准备mapper映射文件(用户配置Java对象,与sql语句对应关系)--新建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:名称空间,相当于java中的package,用于防止sql语句名称冲突(sql语句的隔离) --> <mapper namespace="test"> <!--mybatis针对每一种sql语句:新增/修改/删除/查询, 提供了对应的标签:insert/update/delete/select来放置 --> <!-- 根据用户Id查询用户,说明: select标签:用于放置查询sql语句 id:唯一标识名称 parameterType:输入参数的类型 resultType:输出结果的类型(暂时注意:需要的是全限定名称) #{id}:占位符,相当于jdbc中的? --> <select id="queryUserById" parameterType="int" resultType="domain.User"> select * from `user` where id=#{id} </select> <!-- 根据用户名称模糊查询用户 --> <select id="queryUserByName" parameterType="string" resultType="domain.User"> <!-- select * from `user` where username like #{username} --> <!-- where username like '%小%' ,说明:${value}:字符串拼接符,处理参数--> select * from `user` where username like '%${value}%' </select> <!-- 新增用户 :id是自增长的--> <insert id="insertUser" parameterType="domain.User"> insert into `user`(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address}) insert into `user`(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert> <!-- 根据用户Id修改用户,说明:update:用于放置修改的sql语句--> <update id="updateUserById" parameterType="cn.itheima.po.User"> update `user` set username=#{username},sex=#{sex} where id=#{id} </update> <!-- 根据用户Id删除用户,说明:delete:用于放置删除sql语句--> <delete id="deleteUserById" parameterType="int"> delete from `user` where id=#{id} </delete> </mapper>
7.在sqlMapConfig.xml(主配置文件)中,加载mapper.xml文件
<!-- 加载mapper映射文件 --> <mappers> <!-- 加载User.xml文件,说明: 1.resource:指定配置文件的位置 --> <mapper resource="sqlmap/Mapper.xml"/> </mappers>
8.测试
public class demoTest01 { @Before public void init() throws IOException{ private SqlSessionFactory sqlSessionFactory =null; // 1.加载主配置文件sqlMapConfig.xml /** * getResourceAsStream:从类的根路径下加载主配置文件 */ InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); // 2.读取配置文件内容 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); /** * sqlSessionFactory对象: * 1.它是mybatis框架的核心对象,它是线程安全的,一个项目中只需要一个即可 */ sqlSessionFactory = builder.build(inputStream); } @Test public void queryUserByIdTest() throws IOException{ // 3.使用sqlSessionFactory对象,创建SqlSession对象 /** * sqlSession对象: * 1.它相当于jdbc中的Connection对象,它提供了操作数据库的CRUD方法 * 2.它是线程不安全的,每一个执行的方法都需要创建一个sqlSession */ SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 4.使用sqlSession对象,获取mapper接口的代理对象 /* getMapper:获取mapper接口的代理对象 * 参数: * type:mapper接口的字节码 */ UserMapper mapper = sqlSession.getMapper(UserMapper.class); /** * selectOne:查询单条记录 * 参数: * statement:执行的sql语句(名称空间+"."+sql语句Id) * parameter:传入的参数值 */ // 3.调用方法执行 //查询一条 User user = mapper.queryUserById(2); //模糊查询 List<Object> list = sqlSession.selectList("test.queryUserByName", "%小%"); //新建用户 User user = new User(); user.setXXX("***"); mapper.insertUser(user); //根据ID修改 sqlSession.update("test.updateUserById", user); //根据ID删除 sqlSession.delete("test.deleteUserById", 3); // 5.释放资源 sqlSession.close(); } }
Cache
- 存在内存中的临时数据
- 将用户经常查询的数据放在缓存(内存)中,用户查询的时候就不用从数据库查询
- 从缓存中查数据,减少了数据库的查询次数,从而提高查询效率,解决了高并发系统的性能问题
为什么使用缓存
- 减少与数据库的交互次数,减少系统的开销,提高系统的效率
使用情况
- 经常需要查询并且不经常改变的数据
MyBatis自带二级缓存
- 默认情况是只开启了一级缓存(sqlsession 级别的缓存,也被称为本地缓存)
- 二级缓存需要手动开启和配置,基于namespace级别
- MyBatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存
SqlSession
第一次查询的结构会放在本地缓存,以后相同的方法,相同的参数查询的时候,会直接从缓存拿,没必要去查询数据库
增删改操作一定会刷新缓存
二级缓存也叫全局缓存
机制:
- 一个会话查询一条数据,数据会放到当前会话的一级缓存中
- 如果当前会话关闭了,对应的一级缓存就没了
- 可以把信息放到二级缓存中
- 新的查询就可以从二级缓存中获取
- 不同的名称空间对应不同的二级缓存也就是不同的mapper对应不同的map
<!--显式的开启全局缓存--> <setting name="cacheEnabled" value="true"/> <!--在当前Mapper.xml中使用二级缓存--> <cache/> <--也可以自定义参数--> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>