JDBC 和 mybatis
1. 什么是JDBC,有什么用
JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的数据。
2. jdbc 安装
- 复制mysql-connector-java-5.1.49.jar 到lib 文件夹下
- 右键lib add to library
3. 使用
1. 注册驱动
使用 Class.forName("com.mysql.jdbc.Driver")
- 连接数据库
通过 DriverManager.getConnection(url,user,password) 获取数据库连接
URL: jdbc:mysql://localhost:3306/database
username:root
password:1234
// 1. 驱动 Class.forName("com.mysql.jdbc.Driver"); // 2. 获取连接 String url = "jdbc:mysql://localhost:3306/book"; String user = "root"; String pwd = "root"; Connection con = DriverManager.getConnection(url,user,pwd); if(con != null){ System.out.println("db 连接成功"); }else{ System.out.println("error");
4.JDBC API
5.执行sql 并判断结果
// 3.获取发送sql的对象 Statement statement = conn.createStatement(); // 4. 执行并返回结果 int result = statement.executeUpdate(sql); // 5. 处理结果 if(result == 1){ System.out.println("成功"); }else{ System.out.println("失败"); }
6.资源释放
// 6. 释放资源 statement.close(); conn.close();
- ResultSet (结果集) 查询
// 4. 执行sql ResultSet res = statement.executeQuery("SELECT * FROM user"); // 5. 判断结果 while (res.next()) { String username = res.getString("username"); String password = res.getString("password"); String email = res.getString("email"); System.out.println(username + " " + password + " " + email); } // 6. 释放资源 // ResultSet 也要释放 res.close(); statement.close(); conn.close();
7. DAO data access object
8. 什么是Mybatis
优秀的java 开发的持久层的框架。基于jdbc封装。
9. 安装`mybatis`
1. 在pom.xml中添加maven依赖,然后同步
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency>
2.mybatis 配置
创建mybits-config.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> <!-- 环境配置:事务管理器和数据源配置 --> <environments default="development"> <environment id="development"> <!-- 事务控制级别 JDBC --> <transactionManager type="JDBC"/> <!-- 数据库连接配置 --> <dataSource type="POOLED"> <!-- 相当于引入driver 驱动 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- 连接串url --> <property name="url" value="jdbc:mysql://localhost:3306/pms_one"/> <!-- 用户名 --> <property name="username" value="lc"/> <!-- 密码 --> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!-- 映射器 --> <mappers> <mapper resource="com/brave/dao/mapper/UpmsUserMapper.xml"/> </mappers> </configuration>
10. Mybatis开发步骤
1. 定义entity实体类
2. 定义DAO
3. 编写mapper 文件,编写描述方法
<?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 指定为 DAO --> <mapper namespace="com.study.dao.PushTagDao"> <!-- 描述方法 --> <!-- 里面写sql语句 --> <!-- id 是DAO方法名称,resultType 是entity 的方法 --> <select id="queryPushTag" resultType="com.study.entity.PushTag" > SELECT id,tag_id as tagId, _timestamp as timestamp from cbs_push_tag_table WHERE id = #{arg0} </select> </mapper>
4. 注册Mapper
<mappers> <mapper resource="PushTagDAOMapper.xml"/> </mappers>
5. 测试结果
import com.study.dao.PushTagDao; import com.study.entity.PushTag; 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 java.io.IOException; import java.io.InputStream; public class TestPushTag { public static void main(String[] args) throws IOException { // 1. 加载配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); // 2. 构建sqlsessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 3. 通过 sqlSessionFactory 创建 sqlsession SqlSession sqlSession = sqlSessionFactory.openSession(); // 4. 通过 sqlSession 获得DAO实现类的对象 PushTagDao mapper = sqlSession.getMapper(PushTagDao.class); // 5.测试查询方法 PushTag p1 = mapper.queryPushTag(1); PushTag p2 = mapper.queryPushTag(2); // 输出结果 System.out.println(p1); System.out.println(p2); } }
11. 导入jdbc外部配置到mapper
1. 创建 jdbc.properties
文件
jdbc.url=jdbc:mysql://192.168.32.14:3306/pms_one jdbc.username=lc [email protected] jdbc.driver=com.mysql.jdbc.Driver
2. 在mybatis-config.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> <properties resource="jdbc.properties"></properties> <!-- 环境配置:事务管理器和数据源配置 --> <environments default="development"> <environment id="development"> <!-- 事务控制级别 JDBC --> <transactionManager type="JDBC"/> <!-- 数据库连接配置 --> <dataSource type="POOLED"> <!-- 相当于引入driver 驱动 --> <property name="driver" value="${jdbc.driver}"/> <!-- 连接串url --> <property name="url" value="${jdbc.url}"/> <!-- 用户名 --> <property name="username" value="${jdbc.username}"/> <!-- 密码 --> <property name="password" value="${jdbc.pwd}"/> </dataSource> </environment> </environments> <!-- 映射器 --> <mappers> <mapper resource="PushTagDAOMapper.xml"/> </mappers> </configuration>
12. mybatis 细节配置
1. 别名
这里只需要写到包,不需要写到类!!
2. 添加日志 log4j2
- maven 增加 log4j2
- resources 增加log4j2.xml
// log4j.properties // log4j.properties # 配置根Logger log4j.rootLogger=debug,stdout log4j.logger.org.mybatis.example.BlogMapper=TRACE # 输出信息到控制台 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3. entity 的实体类需要重写一下toString,不然打印的时候只会打印出内存地址
4. 通过实体类或者@Param 传参,而不是arg0
5. 模糊查询的字符拼接
<select id="queryUserByLikeName" resultType="User"> SELECT id,username,password,email FROM user WHERE username Like concat('%',#{username},'%'); </select>
13. CURD
1. 新增(返回自增id)
// 使用自增id的返回自增id <insert id="insertUser" parameterType="User"> <!-- 在插入之后 做点什么--> <!-- keyProperty 把结果设置到该字段上 --> <selectKey order="AFTER" keyProperty="id" resultType="Integer"> SELECT LAST_INSERT_ID(); </selectKey> INSERT INTO user values(NULL,#{username},#{password},#{email}) </insert> <!-- id 方法名称 parameterType 入参类型 useGeneratedKeys 是否自增主键 keyProperty 主键field --> <insert id="insertUser2" parameterType="User" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user values(NULL,#{username},#{password},#{email}) </insert> // 使用before 的事件钩子提前生成一个UUID 的主键 <insert id="insertBook" parameterType="Books"> <selectKey keyProperty="id" resultType="string" order="BEFORE"> SELECT REPLACE(UUID(),'-','') </selectKey> INSERT INTO books VALUES (#{id},#{book_name},#{book_desc},#{price}) </insert>
2. update
<!-- 更新并返回受影响的行数 --> <update id="updateUserById"> UPDATE user SET username = #{username} where id = #{id} </update>
3. delete
<!-- 删除并返回受影响的行数 --> <delete id="deleteUserById"> DELETE FROM user WHERE id= #{id} </delete>
14. 事务
sqlSession.submit(); sqlSession.rollback();
15. 封装工具类
package com.study.utils; import org.apache.ibatis.annotations.Mapper; 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 java.io.IOException; import java.io.InputStream; public class MyBatisUtils{ /** * 利用线程来保证 一个线程内多个实例不同时调用初始化 */ private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>(); private static SqlSessionFactory sqlSessionFactory = null; static { try { // 1. 获取输入 InputStream inputStream = null; inputStream = Resources.getResourceAsStream("mybatis-config.xml"); // 2. 获取sqlSecessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } private static void newSqlSession(){ // 3. 获取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); threadLocal.set(sqlSession); } public static SqlSession getSqlSession(){ // 从线程中获取sqlSession SqlSession sqlSession = threadLocal.get(); // if(sqlSession != null){ return sqlSession; } newSqlSession(); return threadLocal.get(); } }
16. 映射
<!-- 设置字段映射 可以把小驼峰和大驼峰映射起来 --> <resultMap id="books_site" type="Books" > <id column="id" property="id" ></id> <result property="bookName" column="book_name" ></result> <result property="bookDesc" column="book_desc"></result> <result property="price" column="price"></result> </resultMap>
17. 表关系
1. 一对一
// 一对一 <mapper namespace="com.study.dao.SitesDAO"> <resultMap id="sites_result" type="Sites"> <id column="id" property="id"></id> <result column="site_name" property="siteName"></result> <result column="url" property="url"></result> <result column="book_id" property="bookId"></result> <!-- 关联关系:1对1 一本书 对应一个站点 --> <association property="book" javaType="Books"> <id column="bookId" property="id"></id> <result column="book_name" property="bookName"></result> <result column="book_desc" property="BookDesc"></result> <result column="price" property="price"></result> </association> </resultMap> <select id="selectAllSites" resultMap="sites_result"> SELECT books.id bookId,books.book_name,book_desc,books.price,sites.id as id,sites.url,sites.site_name,sites.book_id as bookId FROM books INNER JOIN sites ON sites.book_id = books.id </select> </mapper>
2. 一对多
<?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 指定为 DAO --> <mapper namespace="com.study.dao.UnitDAO"> <resultMap id="unit_staff_obj" type="Unit"> <id column="id" property="id"></id> <result column="name" property="name"></result> <!-- collection 集合 property 和as 的一样, ofType 理解为 as的 javaType --> <collection property="staff" ofType="Staff"> <id column="staff_id" property="id"></id> <result column="staff_name" property="name"></result> <result column="unit_id" property="unitId"></result> </collection > </resultMap> <select id="selectUnitStaffById" resultMap="unit_staff_obj"> SELECT unit.id as id,unit.name as name ,staff.id as staff_id,staff.name as staff_name,staff.unit_id as unit_id FROM unit LEFT JOIN staff ON unit.id = staff.unit_id WHERE unit.id = #{id} </select> </mapper>
3. 多对多
一个user对应多个rule,一个rule对应多个user。
select user.id as userId,user.username as userName,user.email as userEmail,rule.id as ruleId,rule.rule_name as ruleName from user_rule as userRule INNER join user ON userRule.user_id = user.id INNER join rule ON rule.id = userRule.rule_id;
- 定义中间表实体类
user和rule可能都是多个,所以是list
- 定义DAO类
- 定义reusltMap
- 定义mapper描述方法
<?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="com.study.dao.UserRuleDAO"> <resultMap id="one_user_many_rule" type="UserRule"> <id column="id" property="id"></id> <result column="user_id" property="userId"></result> <result column="rule_id" property="ruleId"></result> <collection property="user" ofType="User"> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <result column="email" property="email"></result> </collection> <collection property="rule" ofType="Rule"> <id column="id" property="id"></id> <result column="rule_name" property="ruleName"></result> </collection> </resultMap> <select id="queryUserAndRule" resultMap="one_user_many_rule"> SELECT userRule.id as id,userRule.user_id as user_id, userRule.rule_id as rule_id, rule.rule_name as rule_name,user.username,user.email,user.password FROM user_rule as userRule INNER JOIN user ON user.id = user_id INNER JOIN rule ON rule.id = userRule.rule_id </select> </mapper>
查询结果
sql 执行结果
18. 动态sql
<!-- 动态sql:if --> <select id="queryUserAndRule" resultMap="one_user_many_rule"> SELECT * from user_rule <if test="userId != null"> WHERE user_id = userId </if> </select> <!-- 动态sql:foreach in id的情况下 --> <select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
19. 缓存
- 缓存分为一级缓存和二级缓存
-
- 一级缓存默认开启,sqlSession级别的
- 二级缓存是SqlSessionFactory 级别