1.简单的说一下为什么学习框架,框架的好处?
在中文字典中框架的意思是:比喻事物的整体结构。
这个框架就好像现在我们买房子的时候买的毛坯房,省的以前自己整水泥,砖头自己一步一步搭建房子了那么我们软件中的框架又有什么作用呢?
1.重用代码大大增加,软件生产效率和质量也得到了提高。
2.代码结构的规范化,降低程序员之间沟通以及日后维护的成本
3.软件设计人员要专注于对领域的了解,使需求分析更充分;
4.允许采用快速原型技术; 有利于在一个项目内多人协同工作;
5.开发速度快,成本降低,开发人员少,维护费用降低
2.什么是ORM框架?
我的理解是ORM框架就是把数据库和对象之间的一个映射关系,就是解决我们三层架构中的dao层。
还记得最初链接数据库么?1.加载数据驱动,2.获取数据库链接,3.通过数据库的连接操作数据库,实现增删改查(使用Statement类)4.处理数据库的返回结果,5.关闭链接
String URL="jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&characterEncoding=utf-8";
String USER="root";
String PASSWORD="tiger";
//1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
//2.获得数据库链接
Connection conn=DriverManager.getConnection(URL, USER, PASSWORD);
//3.通过数据库的连接操作数据库,实现增删改查(使用Statement类)
Statement st=conn.createStatement();
ResultSet rs=st.executeQuery("select * from user");
//4.处理数据库的返回结果(使用ResultSet类)
while(rs.next()){
System.out.println(rs.getString("user_name");
}
//关闭资源
rs.close();
st.close();
conn.close();
ORM框架有很多种,这里我只介绍我学过的MyBatis
MyBatis 本是 Apache 的一个开源项目iBatis, 2010 年这个项目由 Apache Software Foundation 迁移到了 Google Code,且改名为 MyBatis 。2013 年 11 月迁移到 GitHub。 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使 用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java 对象)映射成数据库中的记录。 简单的说:MyBatis 是一个半自动 ORM 框架,其本质是对 JDBC 的封装。使用 MyBatis 重点需要程序员编写 SQL 命令,不需要写一行 JDBC 代码。 与 Hibernate 的比较 6 Hibernate 是一个全自动的 ORM 框架。因为 Hibernate 创建了 Java 对象和数据库表 之间的完整映射,可以完全以面向对象的思想来操作数据库,程序员不需要手写 SQL 语句, 而 MyBatis 中还需要手写 SQL 语句,所以是半自动化的,工作量要大于 Hibernate。 为什么半自动化的 Mybatis 比自动化的 Hibernate 受欢迎? MyBatis 需要手写 SQL 语句,所以工作量要大于 Hibernate。但是也正是由于自定义 SQL 语句,所以其灵活性、可优化性就超过了 Hibernate
3.废话不多说,下面介绍MyBatis
(1)先介绍jar包
mybatis-3.5.5.jar | Mybatis 核心 jar 包 |
asm-7.1.jar | 字节码修改框架 |
javassist-3.27.0-GA.jar | 可用来检查、”动态”修改及创建 Java 类。功能与 JDK 自 带反射功能类似,但比反射功能更强大 |
cglib-3.3.0.jar | 反射功能类似,但比反射功能更强大 cglib-3.3.0.jar 实现动态代理的技术,延迟加载时使用 |
ognl-3.2.14.jar | 对象导航图语言的缩写,功能强大的表达式语言工具包。在 动态 SQL 和${param}中使用 |
还有一些其他日志包
(2)核心介绍
SqlSessionFactoryBuilder对象 目的:通过构建着模式构建SqlSessionFactory接口对象
SqlSessionFactory对象 目的:一个数据库连接池,它的作用是创建 SqlSession 接口对象
SqlSession对象 目的:SqlSession 就相当于一个数 据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 方法提交或者回滚事务
Mapper对象 目的:由一个 Java 接口和 XML 文件(或者注解构成),需要给出对应的 SQL 和映 射规则,负责发送 SQL 去执行并返回结果。
学完历史等,下面介绍MyBatis配置文件
Mybatis有两种配置文件:1全局配置文件,2.映射配置文件
全局配置文件名字一般自定义放在src目录下对 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>
<!--引入properties文件-->
<properties resource="db.properties"/>
<!--配置别名-->
<typeAliases>
<typeAlias alias="users" type="com.whq.pojo.Users"></typeAlias>
<package name="com.whq.pojo"/>
</typeAliases>
<!--环境配置-->
<environments default="development">
<environment id="development">
<!--配置事务-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<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>
<!--这里可以配置第二个数据源-->
<environment id="">
<transactionManager type=""></transactionManager>
<dataSource type=""></dataSource>
</environment>
</environments>
<!--引入映射配置文件-->
<mappers>
<!--相对路径引入-->
<mapper resource="com/whq/mapper/UsersMapper.xml"/>
<!--指定映射接口引入-->
<!-- <mapper class="com.whq.mapper.UserMapper"/>-->
<!--使用 filter:///协议指定映射配置文件-->
<!-- <mapper url="file:///D:\code\mybatis\src\com\bjsxt\mapper\UserMapper.xml"/>-->
<!--包的方式引入-->
<!-- <package name="com.whq.mapper"/>-->
</mappers>
</configuration>
这里的配置数据源除了用properties,也可以直接在全局配置文件中写死
除了可以配置以上的数据源,别名,引入映射配置文件外还可以配置
<settings>
<setting name="cacheEnabled" value="true"/> 该配置影响的所有映射器中配置的缓存的全局开关
<setting name="lazyLoadingEnabled" value="true"/> 配置懒加载
<setting name="multipleResultSetsEnabled" value="true"/>当启用时,带有延迟加载属性的对象的加载与否完全取决于对任意延迟属性的调用;反之,每种属性将会按需加载
<setting name="useColumnLabel" value="true"/>是否允许单一语句返回多结果集(需要兼容驱动)。
<setting name="useGeneratedKeys" value="false"/>使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior"
value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods"
value="equals,clone,hashCode,toString"/>
</settings>
映射配置文件:主要是用来编写 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">
<mapper namespace="com.whq.mapper.UserMapper">
<!--查询所有-->
<select id="selectUsersAll" resultType="com.whq.pojo.Users">
select * from users
</select>
<!--根据主键查询所有-->
<select id="selectUsersById" resultType="com.whq.pojo.Users">
select * from users
<where>
<if test="userid != null">
and userid = #{userid}
</if>
</where>
</select>
<!--insert添加用户 -->
<insert id="insertUsers" >
insert into users value (default ,#{username} ,#{usersex})
</insert>
<!--update语句-->
<update id="updateUserById" parameterType="map">
update users set username=#{userName},usersex=#{userSex} where
userid =#{userId}
</update>
<!--还可以自己写个sql出来方便后期用-->
<sql id="selectUser">userid,username,usersex</sql>
<select id="selectUsersById2" resultType="com.whq.pojo.Users">
select <include refid="selectUser"/> from users where userid = #{aaa}
</select>
<delete id="deleteUserById">
delete from users where userid = #{userid}
</delete>
</mapper>
select标签的属性 :
parameterType:指定参数类型。该属性是可选属性。因为 MyBatis 可以通过类型处理 器(TypeHandler)推断出具体传入语句的参数。
resultType:期望从这条语句中返回结果的类全名或别名。
resultMap:使用 resultMap 标签来处理结果集映射
insert标签的属性:
id:当前添加语句的唯一标识,该属性的值不能重复。
parameterType:指定参数类型,可以给定别名。该属性是可选属性。
update标签的属性:
id:当前更新语句的唯一标识,该属性的值不能重复。
parameterType:指定参数类型,可以给定别名。该属性是可选属性
delete 标签的属性:
id:当前删除语句的唯一标识,该属性的值不能重复。
parameterType:指定参数类型,可以给定别名。该属性是可选属性
下面用个小案例来简单的介绍下:
先创建表:
CREATE TABLE `users` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`usersex` varchar(10) DEFAULT NULL,
PRIMARY KEY (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
如果本地没有网可以添加mybatis的dtd约束文件
下 载 dtd : 在 浏 览 器 中 输 入 dtd 的 网 络 地 址 即 可 实 现 下 载 。 比 如 : http://mybatis.org/dtd/mybatis-3-config.dtd 将下载的 dtd 拷贝到本地的一个目录下 Idea 操作路径:File---Settings---Languages & Frameworks 其中 URI 复制 dtd 的网络地址即可。File 选择 dtd 文件在本地的地址。OK!
创建java项目,并且引入相关jar
根据数据库创建实体
public class Users {
private int userid;
private String username;
private String usresex;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsresex() {
return usresex;
}
public void setUsresex(String usresex) {
this.usresex = usresex;
}
}
创建数据库链接配置文件properties,方便日后修改
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjsxt
jdbc.username=root
jdbc.password=root
创建全局配置文件
<?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 文件-->
<properties resource="db.properties"/>
<!--环境的配置-->
<environments default="development">
<environment id="development">
<!-- 配置事务-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源-->
<dataSource type="POOLED">
24
<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="com/whq/mapper/UsersMapper.xml"/>
</mappers>
</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.whq.mapper.UserMapper">
<!--查询所有用户-->
<select id="selectUsersAll" resultType="com.whq.pojo.Users">
select * from users
</select>
</mapper>
创建UsersDao接口和实现类
public interface UsersDao {
List<Users> selectUsersAll()throws IOException;
}
创建实现类
public class UsersDaoImpl implements UsersDao {
/**
* 查询所有用户
* @return
*/
@Override
public List<Users> selectUsersAll()throws IOException {
//创建 SqlSessionFactory 对象
InputStream inputStream =
Resources.getResourceAsStream("mybatis-cfg.xml");
SqlSessionFactory sqlSessionFacotry = new
SqlSessionFactoryBuilder().build(inputStream);
//获取 SqlSession 对象
SqlSession sqlSession = sqlSessionFacotry.openSession();
//通过 SqlSession 对象下的 API 完成对数据库的操作
List<Users> list =
sqlSession.selectList("com.whq.mapper.UserMapper.selectUsersAll");
//关闭 SqlSession 对象
sqlSession.close();
return list;
}
}
写一个测试类
public class Test {
public static void main(String[] args)throws IOException {
UsersDao usersDao = new UsersDaoImpl();
List<Users> list = usersDao.selectUsersAll();
for(Users users:list){
System.out.println(users.getUserid()+"\t"+users.getUsername()+"\t"+users.getUsersex());}
}
}
剩下就可以在映射配置文件中添加select和insert,update等标签去实现增删改查操作
下面介绍一下mybatis中参数绑定的问题
在映射配置文件中向 SQL 语句中绑定参数的语法结构为#{ }和${ }。
#{ } 和 ${ }的区别: #{ } 解析为一个 JDBC 预编译语句(PreparedStatement)的参数标记符占位符 ?。使 用该方式可避免 SQL 注入。 ${ } 仅仅为一个纯碎的 String 替换,在 Mybatis 的动态 SQL 解析阶段将会进行变量替 换。${ } 在预编译之前已经被变量替换了,这会存在 SQL 注入问题。
这里想一个问题,如何保证一次insert,update 同时操作可以同时进行事务的回滚或者新增?
是不是只要能拿到同一个sqlsession就可以,其实就是采用静态方法,代码跑的时候直接生成一个sqlsession,把sqlsession放在threadLocal中
public class MybatisUtils {
private static ThreadLocal<SqlSession> threadLocal = new
ThreadLocal<>();
private static SqlSessionFactory sqlSessionFactory = null;
static{
//创建 SqlSessionFactory
InputStream is = null;
try{
is = Resources.getResourceAsStream("mybatis-cfg.xml");
}catch (IOException e){
e.printStackTrace();
}
sqlSessionFactory = new
SqlSessionFactoryBuilder().build(is);
}
//获取 SqlSession
public static SqlSession getSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession == null){
sqlSession = sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
//关闭 SqlSession
public static void closeSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession != null){
sqlSession.close();
threadLocal.set(null);
}
}
}
这时候在业务层中调用不同的insert,这时候出现异常都可以回滚了
只要调用
sqlSession.rollback();
头一次写博客做分享,以后每周会更新一些自己学的知识点,喜欢的同志以后可以一起探讨,挖掘知识的深度