`
frank-liu
  • 浏览: 1682207 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

mybatis学习总结:annotation与xml结合示例

 
阅读更多

简介

  在之前的文章里讨论过mybatis纯xml或者annotation的开发。同时,也讨论了针对不同对象关系情况下的实现细节。在实际的开发应用中,我们会发现,有时候单纯的使用某一种方式来开发的话并不一定有最佳的效率。比如说当我们使用纯xml的时候,会发现里面有很多比较繁琐的配置,而且因为很多sql语句因为是写在xml配置文件里,一个是容易出错,另外对于一些特殊符号还要做一些处理,这样就显得开发的效率不理想。但是使用annotation的话,如果想要重用一些元素比如ResultMap的话就会比较麻烦,每次要重复定义一些元素。所以,如果能够结合两者一些比较好的地方,对于开发来说会更加理想。

 

示例

SQL脚本

  示例对应的SQL脚本如下:

CREATE TABLE ADDRESSES 
(
  ADDR_ID INT(11) NOT NULL AUTO_INCREMENT,
  STREET VARCHAR(50) NOT NULL,
  CITY VARCHAR(50) NOT NULL,
  STATE VARCHAR(50) NOT NULL,
  ZIP VARCHAR(10) DEFAULT NULL,
  COUNTRY VARCHAR(50) NOT NULL,
  PRIMARY KEY (ADDR_ID)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=LATIN1;

CREATE TABLE STUDENTS 
(
  STUD_ID INT(11) NOT NULL AUTO_INCREMENT,
  NAME VARCHAR(50) NOT NULL,
  EMAIL VARCHAR(50) NOT NULL,
  PHONE VARCHAR(15) DEFAULT NULL,  
  DOB DATE DEFAULT NULL,
  GENDER VARCHAR(6) DEFAULT NULL, 
  BIO LONGTEXT DEFAULT NULL,
  PIC BLOB DEFAULT NULL,
  ADDR_ID INT(11) DEFAULT NULL,  
  PRIMARY KEY (STUD_ID),
  UNIQUE KEY UK_EMAIL (EMAIL),
  CONSTRAINT FK_STUDENTS_ADDR FOREIGN KEY (ADDR_ID) REFERENCES ADDRESSES (ADDR_ID)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=LATIN1;

CREATE TABLE TUTORS 
(
  TUTOR_ID INT(11) NOT NULL AUTO_INCREMENT,
  NAME VARCHAR(50) NOT NULL,
  EMAIL VARCHAR(50) NOT NULL,
  PHONE VARCHAR(15) DEFAULT NULL,  
  DOB DATE DEFAULT NULL,
  GENDER VARCHAR(6) DEFAULT NULL,
  BIO LONGTEXT DEFAULT NULL,
  PIC BLOB DEFAULT NULL,
  ADDR_ID INT(11) DEFAULT NULL,
  PRIMARY KEY (TUTOR_ID),
  UNIQUE KEY UK_EMAIL (EMAIL),
  CONSTRAINT FK_TUTORS_ADDR FOREIGN KEY (ADDR_ID) REFERENCES ADDRESSES (ADDR_ID)  
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=LATIN1;


CREATE TABLE COURSES 
(
  COURSE_ID INT(11) NOT NULL AUTO_INCREMENT,
  NAME VARCHAR(100) NOT NULL,
  DESCRIPTION VARCHAR(512) DEFAULT NULL,
  START_DATE DATE DEFAULT NULL,
  END_DATE DATE DEFAULT NULL,
  TUTOR_ID INT(11) NOT NULL,
  PRIMARY KEY (COURSE_ID),
  CONSTRAINT FK_COURSE_TUTOR FOREIGN KEY (TUTOR_ID) REFERENCES TUTORS (TUTOR_ID)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=LATIN1;


CREATE TABLE COURSE_ENROLLMENT
(
  COURSE_ID INT(11) NOT NULL,
  STUD_ID INT(11) NOT NULL,
  PRIMARY KEY (COURSE_ID,STUD_ID),
  CONSTRAINT FK_ENROLLMENT_STUD FOREIGN KEY (STUD_ID) REFERENCES STUDENTS (STUD_ID),
  CONSTRAINT FK_ENROLLMENT_COURSE FOREIGN KEY (COURSE_ID) REFERENCES COURSES (COURSE_ID)
) ENGINE=INNODB DEFAULT CHARSET=LATIN1;

 

mybatis配置文件  

  对应的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 resource="application.properties"/>
		
	  <typeAliases>
	  	<package name="com.yunzero.domain"/>
	  </typeAliases>
	  <typeHandlers>
	  	<typeHandler handler="com.yunzero.typehandlers.PhoneTypeHandler"/>
	  </typeHandlers>
	
	  <environments default="development">
	    <environment id="development">
	      <transactionManager type="JDBC"/>
	      <dataSource type="POOLED">
	        <property name="driver" value="${jdbc.driverClassName}"/>
	        <property name="url" value="${jdbc.url}"/>
	        <property name="username" value="${jdbc.username}"/>
	        <property name="password" value="${jdbc.password}"/>
	      </dataSource>
	    </environment>
	  </environments>
	  
	  <mappers>
	  	<package name="com.yunzero.mappers"/>
	  </mappers>
  	
</configuration>

  这个文件主要指定数据源和配置环境,另外也指定类型转换和对应的mapper接口。 

 

mapper接口和对应配置文件

  我们这里重点考察TutorMapper,它的对应的配置文件如下:

<?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.yunzero.mappers.TutorMapper">
  	
  	<resultMap type="Course" id="CourseResult">
  		<id 	column="course_id" property="courseId"/>
  		<result column="course_name" property="name"/>
  		<result column="description" property="description"/>
  		<result column="start_date" property="startDate"/>
  		<result column="end_date" property="endDate"/>
  	</resultMap>
  	
  	<resultMap type="Tutor" id="TutorResult">
  		<id 	column="tutor_id" property="tutorId"/>
  		<result column="tutor_name" property="name"/>
  		<result column="email" property="email"/>
  		<result column="phone" property="phone"/>
  		<association property="address" resultMap="com.yunzero.mappers.AddressMapper.AddressResult"/>
  		<collection property="courses"  resultMap="CourseResult"></collection>
  	</resultMap>
  	
</mapper>

  这里定义了两个映射的结果,一个是CourseResult,一个就是TutorResult。这里也引用了其他地方定义的ResultMap。  

  对应的TutorMapper接口定义如下:

public interface TutorMapper {
	@SelectProvider(type=TutorDynaSqlProvider.class, method="findAllTutorsSql")
	List<Tutor> findAllTutors();
	
	@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByIdSql")
	Tutor findTutorById(int tutorId);
	
	@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByNameAndEmailSql")
	Tutor findTutorByNameAndEmail(@Param("name")String name, @Param("email")String email);
	
	@InsertProvider(type=TutorDynaSqlProvider.class, method="insertTutor")
	@Options(useGeneratedKeys=true, keyProperty="tutorId")
	int insertTutor(Tutor tutor);
	
	@UpdateProvider(type=TutorDynaSqlProvider.class, method="updateTutor")
	int updateTutor(Tutor tutor);
	
	@DeleteProvider(type=TutorDynaSqlProvider.class, method="deleteTutor")
	int deleteTutor(int tutorId);
		
	@SelectProvider(type=TutorDynaSqlProvider.class, method="selectTutorById")
	@ResultMap("com.yunzero.mappers.TutorMapper.TutorResult")
	Tutor selectTutorById(int tutorId);
}

  这里有几个值得注意的地方。和前面简单的定义@Select, @Insert等方法不同,这里我们不是直接在这里写sql脚本。因为一方面除了前面提到的在字符串形式写的sql更加容易出错以外,在某些地方,我们需要结合程序逻辑和一些参数做一些更加复杂的运算。也就是动态sql。这些问题使得直接在xml或者annotation里写sql并不是一个很理想的选择。于是mybatis提供了一种比较好的写sql的方法,叫sqlprovider。它使得写sql脚本的代码显得更加面向对象,也显得好理解一点。

 

SQL provider 

  前面示例里使用到的sql provider类详细实现如下:

public class TutorDynaSqlProvider {
	public String findAllTutorsSql() {
		return new SQL() {{
			SELECT("tutor_id as tutorId, name, email");
		    FROM("tutors");
		  }}.toString();
	}

	public String findTutorByIdSql(final int tutorId) {
		return new SQL() {{
			SELECT("tutor_id as tutorId, name, email");
			FROM("TUTORS");
			WHERE("tutor_id = #{tutorId}"); // using placeholder #{tutorId} 
		}}.toString();
	}
	
	public String findTutorByNameAndEmailSql(Map<String, Object> map) {
		return new SQL() {{
			SELECT("tutor_id as tutorId, name, email");
		    FROM("tutors");
		    WHERE("name=#{name} AND email=#{email}");
		}}.toString();
	}
	
	public String insertTutor(final Tutor tutor) {
		return new SQL() {{
			INSERT_INTO("TUTORS");
		    if (tutor.getName() != null) {
		        VALUES("NAME", "#{name}");
		    }
		    
		    if (tutor.getEmail() != null) {
		        VALUES("EMAIL", "#{email}");
		    }
		}}.toString();
	}
	
	public String updateTutor(final Tutor tutor) {
		return new SQL() {{
			UPDATE("TUTORS");
		    
		    if (tutor.getName() != null) {
		    	SET("NAME = #{name}");
		    }
		    if (tutor.getEmail() != null) {
		    	SET("EMAIL = #{email}");
		    }
		    WHERE("TUTOR_ID = #{tutorId}");
		}}.toString();
	}
	
	public String deleteTutor(int tutorId) {
		
		return new SQL() {{
			DELETE_FROM("TUTORS");
		    WHERE("TUTOR_ID = #{tutorId}");
		}}.toString();
		
	}
	
	public String selectTutorById() {	
		return new SQL() {{
			SELECT("t.tutor_id, t.name as tutor_name, email");
			SELECT("a.addr_id, street, city, state, zip, country");
			SELECT("course_id, c.name as course_name, description, start_date, end_date");
			FROM("TUTORS t");
			LEFT_OUTER_JOIN("ADDRESSES a on t.addr_id=a.addr_id");
			LEFT_OUTER_JOIN("COURSES c on t.tutor_id=c.tutor_id");
			WHERE("t.TUTOR_ID = #{id}");
		}}.toString();
	}
}

   通过这部分的实现我们可以看到,我们可以将sql脚本,每个操作对应一个方法。然后在annotation里指定对应的类和方法。针对每个不同的实现,我们来看一下它们的细节。

 

SelectProvider

    SelectProvider里有几种情况,针对没有参数和有参数的情况。在没有参数的情况下,比如findAllTutorsSql,这里只需要在Mapper接口里指定对应的sqlprovider类和方法。在有一个参数的时候,比如有这个方法:

@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByIdSql")
Tutor findTutorById(int tutorId);

  在这里mapper 接口的方法里其实是提供了一个参数的。但是sqlprovider方法里的实现如下:

public String findTutorByIdSql() {
	return new SQL() {{
		SELECT("tutor_id as tutorId, name, email");
		FROM("TUTORS");
		WHERE("tutor_id = #{tutorId}"); // using placeholder #{tutorId} 
	}}.toString();
}

    这里不是简单的做一个sql的拼接,注意到这里将mapper接口里的参数和占位符里的参数一一对应上了。当然,这里的findTutorByIdSql方法并没有带参数。

如果需要provider方法里的方法支持mapper接口里多个参数的话,需要做一些调整。比如mapper接口里有方法:

@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByNameAndEmailSql")
Tutor findTutorByNameAndEmail(@Param("name")String name, @Param("email")String email);

  这里接口指定了两个@Param参数,它就对应sqlprovider提供的参数里需要映射过来的字段。而在这种情况下,sqlProvider对应的方法必须提供一个Map<String, Object>类型的参数。它对应的方法实现如下:

 

public String findTutorByNameAndEmailSql(Map<String, Object> map) {
	return new SQL() {{
		SELECT("tutor_id as tutorId, name, email");
	    FROM("TUTORS");
	    WHERE("name=#{name} AND email=#{email}");
	}}.toString();
}

除了selectprovider,其他的像insertProvider, deleteProvider, updateProvider则相对比较简单直观。它们有一个共同的特点就是所有的sqlprovider方法都必须返回String类型的值。另外,我们也注意到,有的方法里有一些判断的逻辑,比如

public String updateTutor(final Tutor tutor) {		
	return new SQL() {{
		UPDATE("TUTORS");
	    
	    if (tutor.getName() != null) {
	    	SET("NAME = #{name}");
	    }
	    
	    if (tutor.getEmail() != null) {
	    	SET("EMAIL = #{email}");
	    }
	    WHERE("TUTOR_ID = #{tutorId}");
	}}.toString();
}

  这种判断方式如果用纯sql的方式来实现会显得比较麻烦。但是这里用一种类似sql并结合java程序逻辑的方式实现了。它比对应的xml配置方式显得更加灵活。 

 

总结

  总的来说,结合xml, annotaion和sqlprovider的时候,需要注意几个点。一个是mapper的xml配置适合定义一些ResultMap,这样可以方便它们被其他的mapper接口重用。另外,annotation里适合指定对应的sqlprovider以及对应resultMap引用。而对于具体sql语句的编写,在sqlprovider里写则比较合适。而且,要特别注意sqlprovider里方法的参数和mapper接口里方法参数的对应。在这一块,目前感觉还不是很灵活。

 

参考材料

 java persistence with mybatis 3

分享到:
评论

相关推荐

    mybatis学习总结:annotation示例改进

    本篇“mybatis学习总结:annotation示例改进”主要关注的是如何利用MyBatis的注解来优化数据库操作。在现代开发环境中,注解已经成为了简化配置、提高代码可读性的重要工具。以下是关于MyBatis注解使用的一些关键...

    MyBatis-CRUD-Annotation.zip

    在"MyBatis-CRUD-Annotation.zip"这个压缩包中,很显然,它包含了一个关于如何使用MyBatis的注解进行CRUD(创建、读取、更新、删除)操作的示例或教程。以下是对MyBatis中注解使用及相关知识点的详细解释: 1. **...

    Spring boot 示例 官方 Demo

    spring-boot-mybatis-annotation-mulidatasource:springboot+mybatis(注解版)多数据源最简解决方案 spring-boot-thymeleaf:simple spring boot thymeleaf demo spring-boot-jpa-thymeleaf-curd:spring boot + ...

    Spring MVC整合Mybatis

    本篇将详细介绍如何将Spring MVC与Mybatis进行整合,并提供相关配置和操作步骤。 **1. Spring MVC 概述** Spring MVC是Spring框架的一部分,它是一个基于模型-视图-控制器(MVC)设计模式的Web应用框架。它负责处理...

    SpringBoot整合Mybatis示例源码

    SpringBoot和Mybatis是两个非常流行的Java开发框架,SpringBoot简化了Spring的配置,而Mybatis则是一个轻量级的持久层框架,专注于SQL映射和接口操作。本示例源码将展示如何将这两个框架整合在一起,创建一个高效、...

    springmybatis

    1.Configuration.xml 是 mybatis 用来建立 sessionFactory 用的,里面主要包含了数据库连接相关东西,还有 java 类所对应的别名,比如 &lt;typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/&gt; 这个别名...

    [课堂课件讲解]Java微服务实践-Spring Boot MyBatis.pptx

    MyBatis SQL Mapper XML 配置文件用于映射 SQL 模板语句与 Java 类型的配置。 MyBatis SQL Mapper.Annotation MyBatis SQL Mapper.Annotation 是 Java 注解的方式,用于替代 SQL Mapper XML 配置文件。 MyBatis ...

    springboot+mybatis-plus集成

    1. **添加依赖**:在`pom.xml`文件中引入Spring Boot的MyBatis和MyBatis Plus依赖。通常包括`spring-boot-starter-data-jdbc`,`mybatis-spring-boot-starter`以及`mybatis-plus-boot-starter`。 ```xml ...

    spring+mybatis配置

    在提供的"day03_ms"压缩包文件中,可能包含的是关于Spring和MyBatis配置的具体示例代码,如XML配置文件、Mapper接口、映射文件等。通过分析这些文件,可以加深对Spring和MyBatis集成的理解,以及学习如何在实际项目...

    springBoot中mybatis Plus示例

    在本文中,我们将深入探讨如何在SpringBoot应用中集成并使用MyBatis Plus。MyBatis Plus(简称MP)...通过阅读和理解这个示例,你可以更好地掌握SpringBoot与MyBatis Plus的集成方法,以及如何在项目中有效地使用它们。

    Spring Boot Examples

    spring-boot-mybatis-annotation-mulidatasource:springboot+mybatis(注解版)多数据源最简解决方案 spring-boot-thymeleaf:simple spring boot thymeleaf demo spring-boot-jpa-thymeleaf-curd:spring boot +...

    SpringBoot使用MyBatis Plus + 自动更新数据表

    最后,启动Spring Boot应用,通过上述配置,MyBatis Plus将与Spring Boot无缝集成,提供简洁易用的数据操作API,同时实现了数据表的自动更新功能。通过`mybatisPlusDemo`项目中的示例代码,开发者可以更深入地了解这...

    springboot mybatis

    在`pom.xml`文件中添加MyBatis和其与SpringBoot的适配器`spring-boot-starter-mybatis`: ```xml &lt;!-- ...其他依赖... --&gt; &lt;groupId&gt;org.mybatis.spring.boot &lt;artifactId&gt;mybatis-spring-boot-starter ...

    springmvc mybatis集成配置示例

    以下是一个基本的配置示例: ```xml &lt;!-- 数据源配置 --&gt; &lt;bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&gt; &lt;property name="configLocation" value="classpath:...

    Spring Boot整合Mybatis

    4. **编写Mapper XML文件**:与Mapper接口相对应,我们需要创建XML文件来编写具体的SQL语句。在上述配置中,`mybatis.mapper-locations`指定了Mapper XML文件的位置。例如,`src/main/resources/mapper/UserMapper....

    Mybatis Plus环境搭建项目代码

    总结来说,Mybatis Plus的环境搭建主要包括引入依赖、配置数据源和Mybatis Plus参数,以及编写测试类验证其功能。理解并熟练运用Mybatis Plus,可以显著提升你在Java Web开发中的数据库操作效率。

    mybatis-generator-core-chinese-annotation-1.3.5-master.zip

    总的来说,MyBatis Generator Core中文注解版1.3.5为Java开发者提供了一个高效且易用的代码生成解决方案,它降低了与数据库交互的复杂性,使得开发者能够更专注于业务逻辑的实现,提高了开发质量和效率。如果你是...

    springmvc+spring+mybatis

    - `mybatis-config.xml`:MyBatis的配置文件。 5. **jdbc.properties文件**:配置数据库连接的基本信息。 示例内容如下: ``` driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test...

    springBoot-mybatis

    通过学习和理解这个案例,开发者可以快速掌握Spring Boot与MyBatis的整合技巧,进而构建自己的数据驱动应用。这种整合方式在现代企业级应用中非常常见,因为它们结合了Spring Boot的便利性和MyBatis的灵活性,是开发...

Global site tag (gtag.js) - Google Analytics