优点
-
数据库连接,使用时就创建,使用完毕就关闭,这样会对数据库进行频繁的获取连接和关闭连接,造成数据库资源浪费,影响数据库性能。
设想解决:使用数据库连接池管理数据库连接。 -
将 sql 语句硬编码到程序中,如果sql语句修改了,那么需要重新编译 Java 代码,不利于系统维护
设想解决:将 sql 语句配置到 xml 文件中,即使 sql 语句变化了,我们也不需要对 Java 代码进行修改,重新编译。 -
在 PreparedStatement 中设置参数,对占位符设置值都是硬编码在Java代码中,不利于系统维护。
将 sql 语句以及占位符和参数都配置到 xml 文件中。 -
从 resultset 中遍历结果集时,对表的字段存在硬编码,不利于系统维护
设想解决:将查询的结果集自动映射为 Java 对象。 -
重复性代码特别多,频繁的 try-catch
设想解决:将其整合到一个 try-catch 代码块中 -
缓存做的很差,如果存在数据量很大的情况下,这种方式性能特别低。
设想解决:集成缓存框架去操作数据库。 -
sql 的移植性不好,如果换个数据库,那么sql 语句可能要重写。
设想解决:在 JDBC 和 数据库之间插入第三方框架,用第三方去生成 sql 语句,屏蔽数据库的差异。
数据库配置文件
<?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标签,当mybatis和spring整合之后,这个标签是不用配置的 -->
<!-- 可以配置多个运行环境,但是每个 SqlSessionFactory 实例只能选择一个运行环境
一、development:开发模式
二、work:工作模式-->
<environments default="development">
<!--id属性必须和上面的default一样 -->
<environment id="development">
<!--事务管理器
一、JDBC:这个配置直接简单使用了 JDBC 的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围
二、MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期
比如 spring 或 JEE 应用服务器的上下文,默认情况下,它会关闭连接。然而一些容器并不希望这样,
因此如果你需要从连接中停止它,就可以将 closeConnection 属性设置为 false,比如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
-->
<transactionManager type="JDBC"/>
<!--dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象源 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdemo"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
Mapper.xml文件
默认mybatis不会开启 驼峰映射,开启配置:
<configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings> </configuration>
<?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.ys.po.userMapper">
<!-- 根据 id 查询 user 表中的数据
id:唯一标识符,此文件中的id值不能重复
resultType:返回值类型,一条数据库记录也就对应实体类的一个对象
parameterType:参数类型,也就是查询条件的类型
-->
<select id="selectUserById"
resultType="com.ys.po.User" parameterType="int">
<!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 -->
select * from user where id = #{id}
</select>
<!-- 查询 user 表的所有数据
注意:因为是查询所有数据,所以返回的应该是一个集合,这个集合里面每个元素都是User类型
-->
<select id="selectUserAll" resultType="com.ys.po.User">
select * from user
</select>
<!-- 模糊查询:根据 user 表的username字段
下面两种写法都可以,但是要注意
1、${value}里面必须要写value,不然会报错
2、${}表示拼接 sql 字符串,将接收到的参数不加任何修饰拼接在sql语句中
3、使用${}会造成 sql 注入
-->
<select id="selectLikeUserName" resultType="com.ys.po.User" parameterType="String">
select * from user where username like '%${value}%'
<!-- select * from user where username like #{username} -->
</select>
<!-- 向 user 表插入一条数据 -->
<insert id="insertUser" parameterType="com.ys.po.User">
insert into user(id,username,sex,birthday,address)
value(#{id},#{username},#{sex},#{birthday},#{address})
</insert>
<!-- 根据 id 更新 user 表的数据 -->
<update id="updateUserById" parameterType="com.ys.po.User">
update user set username=#{username} where id=#{id}
</update>
<!-- 根据 id 删除 user 表的数据 -->
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
</delete>
</mapper>
如果得到 插入数据之后的 主键值(自增机制)
<!-- 向 user 表插入一条数据 -->
<insert id="insertUser" parameterType="com.ys.po.User">
<!-- 将插入的数据主键返回到 user 对象中
keyProperty:将查询到的主键设置到parameterType 指定到对象的那个属性
select LAST_INSERT_ID():查询上一次执行insert 操作返回的主键id值,只适用于自增主键
resultType:指定 select LAST_INSERT_ID() 的结果类型
order:AFTER,相对于 select LAST_INSERT_ID()操作的顺序
-->
<selectKey keyProperty="id" resultType="int" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,sex,birthday,address)
value(#{username},#{sex},#{birthday},#{address})
</insert>
非自增主键机制
<!-- 向 user 表插入一条数据 -->
<insert id="insertUser" parameterType="com.ys.po.User">
<!-- 将插入的数据主键返回到 user 对象中
流程是:首先通过 select UUID()得到主键值,然后设置到 user 对象的id中,在进行 insert 操作
keyProperty:将查询到的主键设置到parameterType 指定到对象的那个属性
select UUID():得到主键的id值,注意这里是字符串
resultType:指定 select UUID() 的结果类型
order:BEFORE,相对于 select UUID()操作的顺序
-->
<selectKey keyProperty="id" resultType="String" order="BEFORE">
select UUID()
</selectKey>
insert into user(id,username,sex,birthday,address)
value(#{id},#{username},#{sex},#{birthday},#{address})
</insert>
总结:
①、parameterType:指定输入参数的类型
②、resultType:指定输出结果的类型,在select中如果查询结果是集合,那么也表示集合中每个元素的类型
③、#{}:表示占位符,用来接收输入参数,类型可以是简单类型,pojo,HashMap等等
如果接收简单类型,#{}可以写成 value 或者其他名称
如果接收 pojo 对象值,通过 OGNL 读取对象中的属性值,即属性.属性.属性...的方式获取属性值
④、${}:表示一个拼接符,会引起 sql 注入,不建议使用
用来接收输入参数,类型可以是简单类型,pojo,HashMap等等
如果接收简单类型,${}里面只能是 value
如果接收 pojo 对象值,通过 OGNL 读取对象中的属性值,即属性.属性.属性...的方式获取属性值
注解形式
public interface UserMapper {
//根据 id 查询 user 表数据
@Select("select * from user where id = #{id}")
public User selectUserById(int id) throws Exception;
//向 user 表插入一条数据
@Insert("insert into user(username,sex,birthday,address) value(#{username},#{sex},#{birthday},#{address})")
public void insertUser(User user) throws Exception;
//根据 id 修改 user 表数据
@Update("update user set username=#{username},sex=#{sex} where id=#{id}")
public void updateUserById(User user) throws Exception;
//根据 id 删除 user 表数据
@Delete("delete from user where id=#{id}")
public void deleteUserById(int id) throws Exception;
}
测试类
public class UserAnnocationTest {
//定义 SqlSession
SqlSession session =null;
@Before
public void init(){
//定义mybatis全局配置文件
String resource = "mybatis-configuration.xml";
//加载 mybatis 全局配置文件
InputStream inputStream = CRUDTest.class.getClassLoader()
.getResourceAsStream(resource);
//构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//根据 sqlSessionFactory 产生 session
session = sessionFactory.openSession();
}
//注解的增删改查方法测试
@Test
public void testAnncationCRUD() throws Exception{
//根据session获取 UserMapper接口
UserMapper userMapper = session.getMapper(UserMapper.class);
//调用selectUserById()方法
User user = userMapper.selectUserById(1);
System.out.println(user);
//调用 insertUser() 方法
User user1 = new User();
user1.setUsername("aliks");
user1.setSex("不详");
userMapper.insertUser(user1);
//调用 updateUserById() 方法
User user2 = new User();
user2.setId(6);
user2.setUsername("lbj");
userMapper.updateUserById(user2);
//调用 () 方法
userMapper.deleteUserById(6);
session.commit();
session.close();
}
}