MyBatis学习笔记

骑猪看日落 2023-01-09 01:08 188阅读 0赞

StudentMapper.xml中如下编写insert语句:

  1. <insert id="add" parameterType="Student"
  2. useGeneratedKeys="true" keyProperty="id">
  3. insert into student(name,gender,major,grade,supervisor_id)
  4. values(#{name},#{gender},#{major},#{grade},#{supervisor.id})
  5. </insert>

这里的关键是使用了supervisor.id这样的写法,这表明是把学生实体的supervisor属性的id属性值,作为插入的记录的supervisor_id字段的值。其他地方与之前的插入示例一致(MyBatis增删改示例)。

当然在StudentMapper.java中插入实体的方法声明是少不了的,如下:

  1. public void add(Student student);

执行程序如下:

  1. package com.demo;
  2. import org.springframework.context.ApplicationContext;
  3. import com.abc.mapper.StudentMapper;
  4. import com.abc.domain.Student;
  5. import com.abc.domain.Teacher;
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;
  7. public class MyBatisSpringDemo
  8. {
  9. private static ApplicationContext ctx;
  10. static
  11. {
  12. //在类路径下寻找resources/beans.xml文件
  13. ctx = new ClassPathXmlApplicationContext("resources/beans.xml");
  14. }
  15. public static void main(String[] args)
  16. {
  17. StudentMapper mapper =
  18. (StudentMapper)ctx.getBean("studentMapper");
  19. Student student = new Student();
  20. student.setName("李林");
  21. student.setGender("男");
  22. student.setMajor("计算机科学与技术");
  23. student.setGrade("2011");
  24. Teacher supervisor = new Teacher();
  25. supervisor.setId(1);
  26. student.setSupervisor(supervisor);
  27. mapper.add(student);
  28. }
  29. }

执行后,登录MySQL查询。如下图所示:

233948189.png

(注:第一个红框里的命令“set names gbk”是为了能够显示中文。)

从第二个和第三个红框之间的对比可以看出,数据已被写入到数据库(点此进入无事务处理的×××页面)。

二、事务管理

在上面的示例中,并没有为程序配置事务管理器,而在程序中也不像以前的示例那样调用了提交事务的方法,但数据却已实实在在地被写入到了数据库中。这是怎么回事呢?mybatis官方文档告诉我们,凡是在Spring事务之外执行的映射器方法,都会被自动提交(英文可参见http://www.mybatis.org/spring/transactions.html中的“Programmatic Transaction Management”部分,中文可参见http://www.mybatis.org/spring/zh/transactions.html中的“编程式事务管理”部分)。这样一来,就没有用上Spring强大的事务管理功能。Spring事务管理提供声明式(declarative)和编程式(programmatic)两种方式。今天就先给大家介绍一下编程式的基本用法(虽然声明式是最常用的方式,但是发现想把它说清楚不是那么容易滴,留待以后有机会再详述吧)。

首先在Spring的配置文件(本例中为beans.xml)中配置MyBatis-Spring要用到的事务管理器,即org.springframework.jdbc.datasource.DataSourceTransactionManager。配置内容如下:

  1. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  2. <property name="dataSource" ref="dataSource"/>
  3. </bean>

在这里,事务管理器引用了在前面配置的数据源dataSource。显而易见,这个数据源必须是事务管理器所管理的事务将要操作的那个数据源。也就是说,应该与SqlSessionFactoryBean引用同一个数据源。因为我们正是由SqlSessionFactoryBean来获得映射器,进而调用映射器的方法来对数据库进行操作。

需要注意的是,Spring对事务管理做了抽象,提供了统一的编程接口。例如上述的DataSourceTransactionManager事务管理器,实际上是实现了接口org.springframework.transaction.PlatformTransactionManager。针对不同的环境,Spring提供了不同的实现。例如,对于Hibernate,可使用事务管理器org.springframework.orm.hibernate3.HibernateTransactionManager。与此相关的接口还有org.springframework.transaction.TransactionDefinition和org.springframework.transaction.TransactionStatus,分别代表事务的定义和事务的状态。提供统一接口的好处是我们只需要针对这个接口编程,而无需考虑不同环境下事务处理的不同细节。

编程式事务管理代码如下:

  1. package com.demo;
  2. import org.springframework.context.ApplicationContext;
  3. import com.abc.mapper.StudentMapper;
  4. import com.abc.domain.Student;
  5. import com.abc.domain.Teacher;
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;
  7. import org.springframework.transaction.support.DefaultTransactionDefinition;
  8. import org.springframework.transaction.TransactionDefinition;
  9. import org.springframework.transaction.TransactionStatus;
  10. import org.springframework.transaction.PlatformTransactionManager;
  11. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  12. public class MyBatisSpringDemo
  13. {
  14. private static ApplicationContext ctx;
  15. static
  16. {
  17. //在类路径下寻找resources/beans.xml文件
  18. ctx = new ClassPathXmlApplicationContext("resources/beans.xml");
  19. }
  20. public static void main(String[] args)
  21. {
  22. //从Spring容器中请求映射器
  23. StudentMapper mapper =
  24. (StudentMapper)ctx.getBean("studentMapper");
  25. //从Spring容器中请求事务管理器,用PlatformTransactionManager
  26. //类型的引用指向它
  27. PlatformTransactionManager tm =
  28. (PlatformTransactionManager)ctx.getBean("transactionManager");
  29. Student student = new Student();
  30. student.setName("王芳");
  31. student.setGender("女");
  32. student.setMajor("计算机科学与技术");
  33. student.setGrade("2011");
  34. Teacher supervisor = new Teacher();
  35. supervisor.setId(1);
  36. student.setSupervisor(supervisor);
  37. //TransactionDefinition对象代表着事务的定义,即事务的传播行为,
  38. //隔离级别和是否可读等属性。DefaultTransactionDefinition是此
  39. //接口的默认实现,给上述属性指定了默认值。如传播行为是PROPAGATION_REQUIRED,
  40. //只读为false等(可参见Spring api文档)
  41. TransactionDefinition def = new DefaultTransactionDefinition();
  42. //TransactionStatus对象代表着事务的状态。以下代码根据传入的事务定义
  43. //对象返回事务并启动事务
  44. TransactionStatus status = (TransactionStatus)tm.getTransaction(def);
  45. try {
  46. mapper.add(student);
  47. //若执行下述语句,则事务回滚。
  48. //读者可自行验证
  49. //int a = 1/0;
  50. }
  51. catch (Exception e) {
  52. //回滚事务
  53. tm.rollback(status);
  54. e.printStackTrace();
  55. }
  56. //提交事务
  57. tm.commit(status);
  58. }
  59. }

执行结果如下:

234800981.png

查询数据库如下图所示:

234845279.png

显然,数据已被写入。

三、使用bean继承配置映射器

当我们需要在beans.xml中配置多个映射器时,它们的class和sqlSessionFactory属性都是一样的(也许还有其它一样的属性)。显然,我们需要消除这种冗余信息。借助于bean继承机制,我们可以达到这个目的。如下所示:

  1. <bean id="parentMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"
  2. abstract="true">
  3. <!--sqlSessionFactory属性指定要用到的SqlSessionFactory实例-->
  4. <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
  5. </bean>
  6. <bean id="studentMapper" parent="parentMapper">
  7. <!--mapperInterface属性指定映射器接口,用于实现此接口并生成映射器对象-->
  8. <property name="mapperInterface" value="com.abc.mapper.StudentMapper"/>
  9. </bean>

这里的关键是把父bean parentMapper的abstract属性指定为true。这样,Spring就不会创建这个bean实例。它存在的意义是配置好class和sqlSessionFactory这两个属性,供其他子bean继承。而子bean通过把parent属性设置为parentMapper,即可继承这两个属性(点此进入有编程式事务处理和bean继承的源码)。

发表评论

表情:
评论列表 (有 0 条评论,188人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Mybatis学习笔记

    一、引言 1.框架的三层架构     表现层:是用于展示数据(SpringMVC)     业务层:是处理业务需求     持久层:是和数据库交互(MyBati

    相关 Mybatis学习笔记

    学习了Mybatis。相对于hibernate来说这个框架更加灵活,开发效率更快,适用于那些改动比较频繁的项目。 首先加入mybatis的配置文件myBatisConfig.