JavaEE--Mybatis学习笔记(二)--第一个程序
1.新建Java project
2.导入jar包
选中jar包 右键Build Path
3.创建实体类
无参构造方法快速写法 Alt+Shift+s +c
有参构造方法快速写法 Alt+Shift+s +o
getter/setter快速写法 Alt+Shift+s +r
Override toString()快速写法 Alt+Shift+s +s
if else Alt+Shift+z + 3 选中
多行注释 Alt+Shift+j 选中方法名
注释 Ctrl+Shift+/ 选中的算是中文注释
其中 private 后面的是成员变量 而 属性则是去掉get 或者 set 后 第一个字母小写的 就是属性
4.建表
5.配置主配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 3 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 4 <configuration> 5 <!-- 配置运行环境 Ctrl Shift / --> 6 <environments default="mysqlEM"> 7 <environment id="mysqlEM"> 8 <transactionManager type="JDBC" /> 9 <dataSource type="POOLED"> 10 <!-- 使用的是数据库连接池 JDBC也是一种数据源 --> 11 <!-- driver url username password --> 12 <property name="driver" value="com.mysql.jdbc.Driver" /> 13 <!-- jdbc:mysql:/// 就是127.0.0.1:3306 --> 14 <property name="url" value="jdbc:mysql://127.0.0.1:3306/test17182" /> 15 <property name="username" value="root" /> 16 <property name="password" value="123456" /> 17 </dataSource> 18 </environment> 19 <environment id="testEM"> 20 <transactionManager type="JDBC" /> 21 <dataSource type="POOLED"> 22 <!-- 使用的是数据库连接池 JDBC也是一种数据源 --> 23 <!-- driver url username password --> 24 <property name="driver" value="com.mysql.jdbc.Driver" /> 25 <!-- jdbc:mysql:/// 就是127.0.0.1:3306 --> 26 <property name="url" value="jdbc:mysql://127.0.0.1:3306/test17182" /> 27 <property name="username" value="root" /> 28 <property name="password" value="123456" /> 29 </dataSource> 30 </environment> 31 </environments> 32 33 <!-- 注册映射文件 --> 34 <mappers> 35 <mapper resource="com/ryanxu/dao/mapper.xml" /> 36 </mappers> 37 </configuration>
6.映射文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.ryanxu.dao.IStudentDao"> 6 <insert id="insertStudent" parameterType="com.ryanxu.beans.Student"> 7 insert into student(name,age,score) value(#{name},#{age},#{score}) 8 </insert> 9 </mapper>
7.dao 和 dao的实现类
- dao
1 public interface IStudentDao { 2 void insertStu(Student student); 3 }
- dao 的实现类
1 public class IStudentImpl implements IStudentDao { 2 3 private SqlSession sqlSession; 4 5 @Override 6 public void insertStu(Student student) { 7 InputStream inputStream; 8 try { 9 //1.加载主配置文件 10 inputStream = Resources.getResourceAsStream("mybatis.xml"); 11 //使用SqlSessionFactoryBuilder 创建 SqlSessionFactory 由Factory 获取SqlSession 因为SqlSession可以增删改查 12 //2.创建SqlSessionFactory对象 13 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream ); 14 //3.创建SqlSession对象 15 sqlSession = sessionFactory.openSession(); 16 //4.相关操作 17 sqlSession.insert("insertStudent", student); 18 //不写提交的话 会分配id但是不会插入到数据库 所以有提交的话 就会跳一个id 19 sqlSession.commit(); 20 } catch (IOException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 }finally{ 24 if(sqlSession != null){ 25 //用了close() 就不需要事务的回滚 26 sqlSession.close(); 27 } 28 } 29 30 31 } 32 33 }
- 测试类
public class MyTest { private IStudentDao dao; @Before public void before(){ dao = new IStudentImpl(); } @Test public void testInsert(){ Student student = new Student("张三",23,93.5); dao.insertStu(student); } }
可能会报错 java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing 因为4.11以上版本不在包含hamcrest 所以我换成了3.8.1版本的jar包就可以了
- MyBatisUtils
1 public class MyBatisUtils { 2 3 private static SqlSessionFactory sqlSessionFactory; 4 5 /** 6 * SqlSessionFactory 是重量级的 但是是线程安全的 因为没有可修改的属性 所以把它做成单实例的比较好if 7 * sqlSessionFactory 变成成员变量就不用赋初值了 8 * @return 9 */ 10 public static SqlSession getSqlSession(){ 11 InputStream is; 12 try { 13 is = Resources.getResourceAsStream("mybatis.xml"); 14 if(sqlSessionFactory == null){ 15 sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); 16 } 17 return sqlSessionFactory.openSession(); 18 } catch (IOException e) { 19 e.printStackTrace(); 20 } 21 return null; 22 } 23 }
- 改造实现类 IStudentImpl
1 public class IStudentImpl implements IStudentDao { 2 3 private SqlSession sqlSession; 4 5 @Override 6 public void insertStu(Student student) { 7 8 try { 9 sqlSession = MyBatisUtils.getSqlSession(); 10 11 sqlSession.insert("insertStudent", student); 12 13 sqlSession.commit(); 14 } finally{ 15 if(sqlSession != null){ 16 //用了close() 就不需要事务的回滚 17 sqlSession.close(); 18 } 19 } 20 } 21 22 }
- 从属性文件读取DB连接四要素
1 <properties resource="jdbc_mysql.properties"/> 2 <!-- 配置运行环境 Ctrl Shift / --> 3 <environments default="mysqlEM"> 4 <environment id="mysqlEM"> 5 <transactionManager type="JDBC" /> 6 <dataSource type="POOLED"> 7 <!-- 使用的是数据库连接池 JDBC也是一种数据源 --> 8 <!-- driver url username password --> 9 <property name="driver" value="${jdbc.driver}" /> 10 <!-- jdbc:mysql:/// 就是127.0.0.1:3306 --> 11 <property name="url" value="${jdbc.url}" /> 12 <property name="username" value="${jdbc.username}" /> 13 <property name="password" value="${jdbc.password}" /> 14 </dataSource> 15 </environment>
jdbc_mysql.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test17182
jdbc.username=root
jdbc.password=123456
接下去的是源码阅读
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
8.问题及源码阅读
- 输入流的关闭
- SqlSession的创建(成员变量 赋初值)
1. 一般使用的是无参的方法
configuration:是配置文件mybatis.xml
TransactionFactory: 事务工厂我们写的是jdbc
2.接着看DefaultSqlSession
主要功能:赋初值
dirty :内存里的数据和数据库里的数据 不一样就是true的
- 增删改的执行(update 方法)
增删改 底层都是update方法
- SqlSession的提交
autoCommit 和 dirty都是true (快捷键 alt + ← 或 alt + → 进入方法或回去)
因为isCommitOrRollbackRequired方法返回的是true 所以 required 就是 true所以是事务的提交了
- SqlSession的关闭
因为刚刚提交过 所以根据上述的commit()方法 dirty 是 false 并且 openSession方法用的是无参的 所以autoCommit 是 false 且 force 是false 返回值就是false
事务不空 关闭事务
结论:只要没有commit 就会发生回滚
就是之前提到的没写commit 数据库的id被分配出去了,写了commit 数据库里就能插入了
所以主要原因在dirty 执行commit后 会把insert后的dirty设置为false ; 而没有commit的话 只有insert 内存中的数据和数据库中的不一致 dirty就是true了
导致rollback里传进来的就是true 执行了transaction.rollback