学习视频来自黑马程序员,感谢!
对原生态jdbc程序问题总结
环境
java环境:jdk1.8 开发环境:IDEA 数据库 :mysql5.7
jdbc程序
-
数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响 数据库性能。
解决方法:使用数据库连接池管理数据库连接。 -
将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。
解决方法:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。 -
向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
解决方法:将sql语句及占位符和参数全部配置在xml中 -
从result中遍历结果集数据时,存在硬编码,将获取表对字段进行硬编码,不利于系统维护。
解决方法:将查询结果集,自动映射成java对象。
Mybatis框架原理
Mybatis是什么
- 是一个持久层的框架,是apache下的顶级项目
- 让程序员将主要精力放在sql。通过Mybatis提供的映射方式。半自动化生成满足需要sql。
- 可以将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射出java对象。
Mybatis框架
- SqlMapConfig.xml(是Mybatis的全局配置文件)
配置了数据项、事物等Mybatis运行环境 - 多个mapper.xml(配置映射关系、sql语句)
- SqlSessionFactory(会话工厂)根据配置文件创建工厂
作用:创建SqlSession - SqlSeesion(会话) 是一个接口,面向用户
作用:操作数据库(发出sql增删改查) - Executor(执行器),是一个接口(基本执行器、缓存执行器),
作用:SqlSession内部通过执行器操作数据库 - mapped statement(底层分装对象)
作用:对操作数据库存储封装,包括sql语句、输入、输出结果类型
Mybatis入门程序
需求:
- 根据用户id(主键)查询用户信息
- 根据用户名称模糊查询用户信息
- 添加用户
- 删除用户
- 更新用户
创建SqlMapConfig.xml与映射文件User.xml
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>
<!-- 加载属性文件 -->
<properties resource="db.properties">
<!--properties中还可以配置一些属性名和属性值 -->
<!-- <property name="jdbc.driver" value=""/> -->
</properties>
<typeAliases>
<!-- 针对单个别名定义
type:类型的路径
alias:别名
-->
<!-- <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/> -->
<!-- 批量别名定义
指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
-->
<package name="com.caoerzhe.pojo"/>
</typeAliases>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>
</configuration>
User.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有特殊重要的作用
-->
<mapper namespace="test">
</mapper>
根据用户id(主键)查询用户信息
public void findUserById() throws IOException {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂,传入Mybaits文件配置信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过SqlSession操作数据库
// 第一个参数:映射文件中statement的id,等于=namespace+"."+statement的id
// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数
// sqlSession.selectOne结果 是与映射文件中所匹配的resultType类型的对象
// selectOne查询出一条记录
User user = sqlSession.selectOne("test.findUserById",1);
System.out.println(user);
sqlSession.close();
}
根据用户名称模糊查询用户信息
继续使用User.xml,添加根据用户名模糊查询用户信息的sql
根据用户名称模糊查询用户信息,可能返回多条
resultType:指定就是单条记录所映射的java对象类型
${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。
使用${}拼接sql,引起 sql注入
${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value
<select id="findUserByName" parameterType="java.lang.String" resultType="com.caoerzhe.pojo.User">
SELECT * FROM user WHERE username LIKE "%${value}%"
</select>
//查询多条记录
List<User> list = sqlSession.selectList("test.findUserByName","小");
添加用户
1.映射文件
在User.xml配置添加用户的statement
<!-- 添加用户
parameterType:指定输入 参数类型是pojo(包括 用户信息)
#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值
-->
<insert id="insertUser" parameterType="com.caoerzhe.pojo.User">
insert into user (username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
</insert>
2.Java代码
没有spring整合前,要手动提交事物
User user = new User();
user.setUsername("小对的");
sqlSession.insert("test.insertUser",user);
//提交事物
sqlSession.commit();
3.如果设置自增主键,如何返回主键
User.xml
<insert id="insertUser" parameterType="com.caoerzhe.pojo.User">
<!--
将插入数据的主键返回,返回到user对象中
SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键
keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序
resultType:指定SELECT LAST_INSERT_ID()的结果类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
</insert>
4.非自增主键的返回
使用mysql的uuid()函数生成主键,需要修改表中的id字段类型为string,长度设置成35位
执行思路:先通过uuid查询到主键,将主键设置到user对象中。
其次在insert执行时,从user对象中取出id属性值
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
删除用户与更新用户
User.xml
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<!-- 根据id更新用户
分析:
需要传入用户的id
需要传入用户的更新信息
parameterType指定user对象,包括 id和更新信息,注意:id必须存在
#{id}:从输入 user对象中获取id属性值
-->
<update id="updateUser" parameterType="com.caoerzhe.pojo.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
Java代码
sqlSession.insert("test.insertUser",user);
sqlSession.update("test.updateUser",user);
小结
- parameterType
在映射文件中通过parameterType指定输入类型 - resultType
在映射文件中通过resultType指定输出结果类型 - #{}与${}
#{} 表示一个占位符 ,类型可以是简单类型,pojo,hashmap。 若果是简单类型,#{}中可以写成value或其他名称。 ${} 表示一个拼接符,会引起sql注入,不建议使用 ,也能简单,pojo,hashmap。 但是接受简单类型,只能用value - selectOne和selectList
selectOne 表示查询出一条记录进行映射 selectList 表示查询出一个列表进行映射