MyBatis入门--第一天
来源:互联网 发布:光纤分路器 什么网络 编辑:程序博客网 时间:2024/05/17 08:55
mybatis 入门
下载:https://github.com/mybatis/mybatis-3/releases
对原生态jdbc程序中问题总结
1 数据库连接,使用时创建,不使用立即释放,对数据库进行频繁连接开启或关闭,造成数据库资源浪费,影响数据库性能。
解决方案:使用数据库连接池管理数据库连接
2 将sql语句硬编码到java代码中,如果sql语句更改,需要重新编译java代码,不利于系统维护(硬编码:代码写死了)
解决方案:将sql语句配置在xm配置文件中,即使sql变化,不需要对java代码进行重新编译
3 向preparedstatement中设置参数,对占位符位置和设置参数,硬编码在java代码中,不利于系统维护
解决:将sql语句及占位符位置和设置参数全部配置在xml
4 从resultset中遍历结果集数据时,存在硬编码,将获取表的字段进行了硬编码,不利于系统维护
解决:将查询的结果集自动映射成java对象
mybatis框架:
mybatis是一个持久层的框架,是apache下的顶级项目
mybatis 将SQL语句独立在Java代码之外,为程序的修改和纠错提供了更大的灵活性,可以直接修改SQL语句,而无需重新编译Java程序。
mybatis可以将preparedstatement中输入参数自动进行输入映射,将查询结果集灵活映射出java对象(输出映射)
mybatis
hibernate:重量级框架 封装了很多东东 ,不好带代码进行优化 struts
mybatis: 轻量级 封装jdbc ---映射
ibatis ----- mybaits
awt swing
,mybatis中首先要在配置文件中配置一些东西,然后根据这些配置去创建一个会话工厂,再根据会话工厂创建会话,会话发出操作数据库的sql语句,然后通过执行器操作数据,再使用mappedStatement对数据进行封装
需求:
mybatis驱动包+sql驱动包
步骤:
1 src下新建log4j.properties文件 或在项目下新建source folder文件夹,把配置文件放在里面也行(项目下的第一级source folder文件夹就相当于src),
source folder和folder区别:source folder文件夹下放要用到的java配置文件,如xml,java会编译执行它,而普通folder文件夹放一些程序员自己管理的文件,如图片等,java不会编译执行它
配置:
注意:开发环境下设置DEBUG,生产环境下设置info或error(用于调试)
#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
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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="jdbc:sqlserver://127.0.0.1:1433;databasename=userDB"/>
<property name="username" value="sa"/>
<property name="password" value="123"/>
</dataSource>
</environment>
</environments>
</configuration>
如果是mysql
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/xxx" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
3 创建映射文件 (例子:根据id查询)
(1) 原始的ibatis的命名方式 :user.xml
(2)mapper代理开发映射方式:xxxmapper.xml如usermapper.xml
这里使用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语句封装到mappedStatement对象中,所以将id称为statement的id
#{}表示一个占位符:会自动在外包裹引号:如果是order by #{xx}相当于 order by‘值’
如果输入参数是简单类型(String,int,double..),#{}中的参数名可以任意写
#{id}:其中的id表示输入参数名
parameterType:指定输入参数类型,这里指定int型
resultType:返回结果集类型User_tb是写的一个和表对应的类,这里写完整的包名类名
-->
<select id="findUserById" parameterType="int" resultType="com.beans.User_tb">
select * from user_tb where id=#{id}
</select>
</mapper>
3.5 同时封装类如:
public class User_tb {
//属性名和数据库表的字段对应
private int id;
private String name;
private String sex;
private Date birthday;
private String address;
4 在SqlMapConfig.xml的 configuration下最末尾加载映射文件
<mappers>
<mapper resource="user_tb.xml" />
</mappers>
最终的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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="jdbc:sqlserver://127.0.0.1:1433;databasename=userDB"/>
<property name="username" value="sa"/>
<property name="password" value="123"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="user.xml" />
</mappers>
</configuration>
5获取一行数据: selectOne()
//mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream is= Resources.getResourceAsStream(resource);
//创建会话工厂,传入mybatis的配置文件信息
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
//通过工厂得到SqlSession
SqlSession sqlsession=ssf.openSession();
//通过SqlSession操作数据库
//第一个参数:映射文件中statement的id,等于 namespace+"."+statement的id
//第二个参数:指定和映射文件中所匹配的paramenterType类型参数
//sqlsession.selectOne结果是与映射文件中所匹配的resultType类型对象
User_tb user= sqlsession.selectOne("test.findUserById", 1);
System.out.println(user);
//释放会话资源
sqlsession.close();
例子:根据用户名模糊查询 selectList()
步骤:使用User.xml
<!-- 根据用户名模糊查询用户信息,可能返回多条
${}:表示拼接sql串,( 将传入的数据直接显示在sql语句中(传的是什么就是什么,不会在外面自动添加引号))如果传递的是order by ${xx} –order by值
但使用${}拼接sql,引起sql注入攻击,但没办法,如果是#{}能够防止sql注入攻击
${value}:接受输入参数内容,如果传入类型是简单类型,${}中只能使用value
一般${}用于like模糊匹配,尽量用#
-->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.beans.User_tb">
select * from user_tb where name like '%${value}%'
</select>
主函数:
// 根据用户名模糊查询用户信息
public static void findUserByName()throws IOException{
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
List<User_tb> list=sqlsession.selectList("test.findUserByName","张");
System.out.println(list.size());
}
添加用户:
使用User.xml
<!-- 添加用户
parameterType:指定输入参数类型是对象
#{}中指定对象的属性名,接受到对象的属性,mybatis通过OGNL获取对象的属性值-->
<insert id="addUser" parameterType="com.beans.User_tb">
insert into user_tb values (#{name},#{sex},#{birthday},#{address})
</insert>
主函数:
//添加用户
public static void addUser()throws IOException{
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
//创建对象
User_tb u=new User_tb("校花","男", new Date(),"河南");
sqlsession.insert("test.addUser",u );
//提交事务
sqlsession.commit(); //增删改需要提交事务
//关闭会话
sqlsession.close();
}
自增主键返回:执行insert提交之后自动生成一个自增主键,该主键用于外键表的操作
通过函数获取到刚刚插入记录的自增主键 select @@IDENTITY
(mysql的语法为:select last_insert_id())
使用User.xml
<insert id="addUser" parameterType="com.beans.User_tb">
<!-- 将插入数据的主键返回,返回到user对象中
select @@IDENTITY:得到刚insert进去记录的主键值,只适用于自增主键
keyProperty:将查询到主键值设置到 parameterType 指定的对象的哪个属性
order: select @@IDENTITY 执行顺序,相对于insert语句来说它的执行顺序
SelectKey需要注意order属性,像MySQL一类支持自动增长类型的数据库中,order需要设置为after才会取到正确的值。像Oracle这样取序列的情况,需要设置为before,否则会报错。
resultType:指定 select @@IDENTITY的结果类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select @@IDENTITY
</selectKey>
insert into user_tb values (#{name},#{sex},#{birthday},#{address})
</insert>
主函数:在提交(sqlsession.commit();)后面可以打印测试u.getId()
删除用户:
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user_tb where id=#{id}
</delete>
更新用户
<!-- 更新用户 -->
<update id="updateUser" parameterType="com.beans.User_tb">
update user_tb set name=#{name},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}
</update>
总结:#{} 和 ${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
能用#{}就不要用${}
mybatis排序时使用order by动态参数时需要住哟,使用$而不是#
1.1.1 selectOne和selectList
selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。
selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。
如果使用selectOne报错:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4
1.1 mybatis和hibernate本质区别和应用场景
hibernate:是一个标准ORM框架(对象关系映射)。入门门槛较高的,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的。
应用场景:
适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。
(因为hibernate是一个重量级框架)
mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis也可以实现映射(输入映射、输出映射)。
应用场景:
适用与需求变化较多的项目,比如:互联网项目。
企业进行技术选型,以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。
1.1.1 SqlSession
SqlSession是一个面向用户(程序员)的接口。
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。
SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性???。
SqlSession最佳应用场合在方法体内,定义成局部变量使用。
原始dao开发方法(程序员需要写dao接口和dao实现类)
1.1.2 dao接口
步骤:
1 写dao接口
public interface UserDao {
//根据id查询用户
public User_tb findUserById(int id)throws Exception;
//添加
public void addUser(User_tb user)throws Exception;
//删除
public void delUser(int id)throws Exception;
}
2 写该接口的实现类
public class UserDaoImplimplements UserDao {
//需要向dao实现类注入SqlSessionFactory
//这里通过构造方法注入
private SqlSessionFactoryssf;
public UserDaoImpl(SqlSessionFactory ssf) {
this.ssf = ssf;
}
@Override
public User_tb findUserById(int id)throws Exception {
SqlSession sqlSession=ssf.openSession();
User_tb user= sqlSession.selectOne("test.findUserById", id);
sqlSession.close();
return user;
}
@Override
public void addUser(User_tb user)throws Exception {
SqlSession sqlsession=ssf.openSession();
//创建对象
sqlsession.insert("test.addUser",user);
//提交事务
sqlsession.commit();
//关闭会话
sqlsession.close();
}
@Override
public void delUser(int id)throws Exception {
SqlSession sqlsession=ssf.openSession();
sqlsession.delete("test.deleteUser", 4);
//提交事务
sqlsession.commit();
//关闭会话
sqlsession.close();
}
测试代码:
public class dao测试 {
public static void main(String[] args)throws Exception {
String resource="SqlMapConfig.xml";
InputStream is= Resources.getResourceAsStream(resource);
SqlSessionFactory ssf= new SqlSessionFactoryBuilder().build(is);
SqlSession sqlsession=ssf.openSession();
UserDaoImpl udi=new UserDaoImpl(ssf);
User_tb u= udi.findUserById(2);
System.out.println(u);
}
}
1.1.3 总结原始 dao开发问题
1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
2、调用sqlsession方法时将statement的id硬编码了:即类似于”test.findUserById”这种,都写死了。
3、sqlSession的方法中,要求传入的参数是Object类型的(泛型),也就是说如果我传错了参数,编译不会报错,执行的时候才会报错,不利于开发。如
- MyBatis入门--第一天
- MyBatis第一天
- Mybatis第一天
- mybatis开发(第一天)
- Mybatis学习第一天
- mybatis第一天笔记
- Mybatis学习第一天
- Mybatis学习第一天
- Flex 入门第一天
- 入门第一天
- delphi入门第一天
- php入门第一天
- android入门第一天
- CATIA入门第一天
- web入门第一天
- 入门网络安全第一天
- HTML第一天入门
- 第一天 基础入门
- Spark 共享变量
- 任务调度程序
- LeetCode 26. Remove Duplicates from Sorted Array
- 8080端口被占用问题
- CF827D,巧妙的图(树)论题
- MyBatis入门--第一天
- 暑假集训 二叉树 大话数据结构上讲的
- 安卓利用LoaderManager 检测数据源变化
- Oracle分组函数之ROLLUP魅力
- Centos7搭建FTP服务器步骤
- JAVA内存模型及垃圾回收自我总结
- RocketMQ原理解析-broker 3.load&recover
- (三)DCF机制详解_下篇
- [Leetcode] 291. Word Pattern II 解题报告