mybatis自己学习的一些总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis自己学习的一些总结相关的知识,希望对你有一定的参考价值。

曾经一直在使用spring的JDBCTEMPLATE和hibernate做项目。两个都还不错,spring的jdbctemplate用起来比較麻烦,尽管非常easy。而hibernate呢,用起来非常好用,非常方便,可是非常多规矩,规则还有方法到如今都还是入门阶段。所以我就学习了一下mybatis来充实一下自己。

mybatis的学习(我也仅仅是入门),我參考了这个博客地址----大神的总结。通过对他的博客的一些学习。我做了一些自己的总结,所以以下的一些内容都是自己在学习的时候的一些东西,也是參考着大神的博客来做的。当然做了一些错误的改动和自己理解的实现。

mybatis实战教程(mybatis in action)之中的一个:开发环境搭建

1.关于数据库表的创建,參见大神的博文,这里就不再多说;

2.在user_src下的Configuration.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>
	<!--这里给我们要使用的数据实体类设置一个在mybatis中使用的别名。以后在mybatis中直接使用他们的别名来映射到相应的实体对象中 -->
	<typeAliases>
		<typeAlias alias="User" type="com.mpc.mybaits.model.User" />
		<typeAlias alias="Article" type="com.mpc.mybaits.model.Article" />
	</typeAliases>

	<!-- 指定mybatis中使用的数据库环境。默认使用development,当中development使用的是JDBC来链接数据库,数据库是mysql -->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybaits" />
				<property name="username" value="root" />
				<property name="password" value="root" />
			</dataSource>
		</environment>
	</environments>

	<!--这里使用mapper来指定相应的实体类的处理方法,(这些mapper就是处理数据的增删改查方法的xml集合,在这里面你能够写不论什么的查询方法 
		。在这些xml中我们能够使用typeAliases中申明的对象来包装我们的查询结果,传入查询參数), 这写mapper都是能够写随意的查询方法的。(随意的表,随意的查询语句)可是在开发中我们为每个类指定一个mapper文件,这样是为了方便管理和项目的开发 
		。总之就是一点:mapper和typeAliases是没有不论什么相应关系的,仅仅是为了开发方便才会有什么Usermapper、Articlemapper这些分类 -->
	<mappers>
		<mapper resource="com/mpc/mybaits/model/User.xml" />
	</mappers>
</configuration>

3.详细User类的实现參照大神的博文,我这里就不献丑了。仅仅说一句:这个类是用在typeAliases那里的。

4.和User类在同一个包下的User.xml。这个User.xml是用在mappers中的,它的作用是提供数据库增删改查的方法。

<?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">
<!-- 这里我们要通过xml来进行数据库的操作,所以我饿美女给这个mapper指定一个唯一的空间名称, -->
<mapper namespace="com.mpc.mybaits.model.UserMapper">

	<!-- 这里定一个select方法。从user表中查找指定id的数据。然后用 resultType="User" User类来进行包装 -->
	<!--  id是这种方法的唯一标识,通过id来调用这种方法,parameterType是传入的參数的类型。这里是整形。通过#{xxx}来获得传入的參数-->
	<select id="selectUserByID" parameterType="int" resultType="User">
		select * from `user` where id = #{id}
	</select>

</mapper>
5.建立測试类

package com.mpc.test;

import java.io.Reader;

import lombok.Getter;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Assert;
import org.junit.Test;

import com.mpc.mybaits.model.User;

public class Test1 {

	private static @Getter SqlSessionFactory sqlSessionFactory;
	private static Reader reader;

	static {// 在一个static块中处理我们的相关初始化操作,这里做的操作是用Configuration.xml中的配置信息来初始化一个mybatis使用的sqlSessionFactory
		try {
			reader = Resources.getResourceAsReader("Configuration.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Test
	public void test() {
		SqlSession session = sqlSessionFactory.openSession();// 获得session
		Assert.assertNotNull(session);// 断言session不为空
		try {
			// 通过session来调用com.mpc.mybaits.model.UserMapper.selectUserByID方法。传入的參数是1
			// 当中com.mpc.mybaits.model.UserMapper是我们的mapper的命名空间。

selectUserByID是方法的id User user = (User) session.selectOne( "com.mpc.mybaits.model.UserMapper.selectUserByID", 1); Assert.assertNotNull(user);// 断言user不为空 Assert.assertEquals( "User(id=1, userName=summer, userAge=100, userAddress=shanghai,pudong)", user.toString());// 对user内容的断言 } finally { session.close();// 最后要关闭session } } // public static void main(String[] args) { // SqlSession session = sqlSessionFactory.openSession(); // try { // User user = (User) session.selectOne( // "com.mpc.mybaits.model.UserMapper.selectUserByID", 1); // System.out.println(user.toString()); // } finally { // session.close(); // } // } }


測试结果:

技术分享

技术分享


mybatis实战教程(mybatis in action)之二:以接口的方式编程

使用接口编程的方式能够提高我们在方法中使用mybatis的效率。降低非常多不必要错误,让我们不用总是查来查去,思来想去。。

1.在inter包中定义我们的接口

package com.mpc.mybaits.inter;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Param;

import com.mpc.mybaits.model.Article;
import com.mpc.mybaits.model.User;
import com.mpc.mybaits.utils.PageInfo;

/**
 * @author Administrator
 *
 */
public interface IUserOperation {

	/**
	 * 方法的名称必须与User。xml中的 select 的id 相应(<select id="selectUserByID")
	 * 
	 * @param id
	 * @return
	 */
	public User selectUserByID(int id);

	
}
2.改动user.xml

<?

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="ccom.mpc.mybaits.inter.IUserOperation"> <!-- 这里定一个select方法,从user表中查找指定id的数据,然后用 resultType="User" User类来进行包装 --> <!-- id是这种方法的唯一标识,通过id来调用这种方法,parameterType是传入的參数的类型,这里是整形。

通过#{xxx}来获得传入的參数--> <select id="selectUserByID" parameterType="int" resultType="User"> select * from `user` where id = #{id} </select> </mapper>

3.測试方法

package com.mpc.test;

import java.io.Reader;

import lombok.Getter;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.User;

public class Test2 {
	private static @Getter SqlSessionFactory sqlSessionFactory;
	private static Reader reader;

	static {
		try {
			reader = Resources.getResourceAsReader("Configuration.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Test
	public void test() {
		new Test1();
		SqlSession session = sqlSessionFactory.openSession();

		try {
			IUserOperation iUserOperation = session
					.getMapper(IUserOperation.class);//通过session来获得IUserOperation的实例对象
			User user = iUserOperation.selectUserByID(1);//直接调用接口中 的方法就能够了
			System.out.println(user.toString());
		} finally {
			session.close();
		}
	}
}

測试结果:

技术分享

mybatis实战教程(mybatis in action)之三:实现数据的增删改查

*用list来返回多个查询结果。要使用list来返回多个查询结果,那么我们要定义自己的resultMap;

在User.xml中增加自定义的resultMap。

	<!-- 为了返回list 类型而定义的returnMap -->
	<resultMap type="User" id="resultListUser">
		<id column="id" property="id" />
		<result column="userName" property="userName" />
		<result column="userAge" property="userAge" />
		<result column="userAddress" property="userAddress" />
	</resultMap>


这是大神的博文中提到的,可是依据我自己的实践···这里全然没有必要使用resultMap,使用resultType就能够达到目的,所以我在user.xml中使用例如以下语句也是能够的:

	<select id="selectUsers" parameterType="string" resultType="User">
		select * from user where userName like #{userName}
	</select>

当然依照大神的博文中记载的方式也是能够的--》在User.xml中增加新的查询语句。

	<!-- 返回list 的select 语句。注意 resultMap 的值是指向前面定义好的 -->
	<select id="selectUsers" parameterType="string" resultMap="resultListUser">
		select * from user where userName like #{userName}
	</select>


个人理解,resultMap就是我们自定义的一种返回结果的包装。在从表中查处数据口。MyBatis把全部的查询结果都放在一个map中,都是用key-value的形式存放的。假设指定的是resultType。那么Mybatis会为我们进行封装。指定的为resultMap的话。Mabatis会依照resultMap定义的格式来进行封装而已-----------。


在IUserOperation接口中增加resulListUser这个id相应的接口方法----
public List<User> selectUsers(String userName);


測试方法:

package com.mpc.test;

import java.io.Reader;
import java.util.List;

import lombok.Getter;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.User;

public class Test2 {
	private static @Getter SqlSessionFactory sqlSessionFactory;
	private static Reader reader;

	static {
		try {
			reader = Resources.getResourceAsReader("Configuration.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Test
	public void test() {
		new Test1();
		SqlSession session = sqlSessionFactory.openSession();

		try {
			IUserOperation iUserOperation = session
					.getMapper(IUserOperation.class);// 通过session来获得IUserOperation的实例对象
			List<User> list = iUserOperation.selectUsers("%");
			for (int i = 0; i < list.size(); i++) {
				System.out.println(list.get(i).toString());
			}
		} finally {
			session.close();
		}
	}
}


測试结果:

技术分享

*使用mybatis来添加数据

在User.xml中加入例如以下代码:

	<!--运行添加操作的SQL语句。id和parameterType 分别与IUserOperation接口中的addUser方法的名字和 參数类型一致。

以#{name}的形式引用Student參数 的name属性,MyBatis将使用反射读取Student參数 的此属性。

#{name}中name大写和小写敏感。引用其它 的gender等属性与此一致。seGeneratedKeys设置 为"true"表明要MyBatis获取由数据库自己主动生成的主 键。keyProperty="id"指定把获取到的主键值注入 到Student的id属性 --> <insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id"> insert into user(userName,userAge,userAddress) values(#{userName},#{userAge},#{userAddress}) </insert>


在IUserOperation接口中增加addUser这个id所相应的接口方法public void addUser(User user);

Mybatis在接受到user对象以后,会把user的属性都封装到一个map中,key是user的属性名。value就是user的属性值了。

所在通过#{属性名}在user.xml中就能取得传入的user的属性值。

測试方法:

package com.mpc.test;

import java.io.Reader;

import lombok.Getter;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.User;

public class Test3 {
	private static @Getter SqlSessionFactory sqlSessionFactory;
	private static Reader reader;

	static {
		try {
			reader = Resources.getResourceAsReader("Configuration.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		User user = new User();
		user.setUserAddress("人民广场123");
		user.setUserName("飞鸟123");
		user.setUserAge("80123");
		SqlSession session = sqlSessionFactory.openSession();
		try {
			IUserOperation iUserOperation = session
					.getMapper(IUserOperation.class);
			iUserOperation.addUser(user);
			session.commit();// 必须的,不然的话是保存不到数据库中的
			System.out.println("加入了用户,当前用户的id为" + user.getId());
		} finally {
			session.close();
		}
	}
}

測试结果:

技术分享


技术分享


*使用mybatis来更新数据

在User.xml中加入例如以下代码

	<update id="updateUser" parameterType="User">
		update user set
		userName=#{userName},userAge=#{userAge},userAddress=#{userAddress}
		where id=#{id}
	</update>

在IUserOperation中加入相应的接口方法

public void updateUser(User user);


測试方法

package com.mpc.test;

import java.io.Reader;

import lombok.Getter;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.User;

public class Test4 {
	private static @Getter SqlSessionFactory sqlSessionFactory;
	private static Reader reader;

	static {
		try {
			reader = Resources.getResourceAsReader("Configuration.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		SqlSession session = sqlSessionFactory.openSession();
		try {
			IUserOperation iUserOperation = session
					.getMapper(IUserOperation.class);
			User user = iUserOperation.selectUserByID(6);
			user.setUserAddress("太平天国");
			iUserOperation.updateUser(user);
			session.commit();// 必须的。不然的话是保存不到数据库中的
			System.out.println("更新了用户,当前用户的id为" + user.getId());
		} finally {
			session.close();
		}
	}
}


測试结果

技术分享

技术分享


*mybatis删除数据

在User.xml中加入例如以下代码

	<delete id="deleteUser" parameterType="int">
		delete from user where
		id=#{id}
	</delete>
在IUserOperaiton中加入相应的接口方法:

	public void deleteUser(int id);

測试方法:

package com.mpc.test;

import java.io.Reader;

import lombok.Getter;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.User;

public class TestDelete {
	private static @Getter SqlSessionFactory sqlSessionFactory;
	private static Reader reader;

	static {
		try {
			reader = Resources.getResourceAsReader("Configuration.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		SqlSession session = sqlSessionFactory.openSession();
		try {
			IUserOperation iUserOperation = session
					.getMapper(IUserOperation.class);
			User user = iUserOperation.selectUserByID(4);
			iUserOperation.deleteUser(6);
			session.commit();// 必须的,不然的话是保存不到数据库中的
			System.out.println("删除了用户,当前用户的id为" + user.getId());
		} finally {
			session.close();
		}
	}
}


mybatis实战教程(mybatis in action)之四:实现关联数据的查询

1.article表和实体的创建參加大神的博文,这里我就不写了。

2.在User.xml中加入例如以下代码

	<!-- User 联合文章进行查询 方法之中的一个的配置 (多对一的方式) -->
	<resultMap id="resultUserArticleList" type="Article">
		<id property="id" column="aid" />
		<result property="title" column="title" />
		<result property="content" column="content" />

		<association property="user" javaType="User">
			<id property="id" column="id" />
			<result property="userName" column="userName" />
			<result property="userAddress" column="userAddress" />
			<result property="userAge" column="userAge" />
		</association>
		<!-- <association property="user" javaType="User" resultMap="resultListUser" 
			/> -->
	</resultMap>
这里要使用到resultMap,由于我们的数据库中的表结构和我们自定义的类的字段是不正确应的。通过联合查询以后。mybatis并不知道要用如何的映射关系来专配。所以我们在这里自定义。

在User.xml中增加查询代码

	<select id="getUserArticles" parameterType="int"
		resultMap="resultUserArticleList">
		select user.id,user.userName,user.userAddress,user.userAge,article.id
		aid,article.title,article.content from user,article
		where
		user.id=article.userid and user.id=#{id}
	</select>
3.在IUserOperation中增加对应的接口方法

public List<Article> getUserArticles(int userid);
4.測试方法

package com.mpc.test;

import java.io.Reader;
import java.util.List;

import lombok.Getter;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.Article;
import com.mpc.mybaits.model.User;

public class Test5 {
	private static @Getter SqlSessionFactory sqlSessionFactory;
	private static Reader reader;

	static {
		try {
			reader = Resources.getResourceAsReader("Configuration.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		SqlSession session = sqlSessionFactory.openSession();
		try {
			IUserOperation iUserOperation = session
					.getMapper(IUserOperation.class);
			List<Article> articles = iUserOperation.getUserArticles(1);
			System.out.println(articles.size());
			for (Article article : articles) {
				System.out.println(article.getUser().toString());
				
				System.out.println(article.getTitle() + ":"
						+ article.getContent() + ":作者是:"
						+ article.getUser().getUserName() + ":地址:"
						+ article.getUser().getUserAddress());
			}
		} finally {
			session.close();
		}
	}
}
5.測试结果

技术分享


也能够在已经定义好user的resultMap的情况下。在association处直接使用

<association property="user" javaType="User" resultMap="resultListUser" 
			/>
来做关联查询,这个大神博文中有,我就不做解释了。


mybatis实战教程(mybatis in action)之五:与spring3集成
mybatis实战教程(mybatis in action)之六:与Spring MVC 的集成
mybatis SqlSessionDaoSupport的使用

在大神的博文中。这三个是分开写的。这里我就整合到一起了,使用spring。一般也会用springmvc。然后SqlSessionDaoSupport这个的话,我认为不是必需去在乎,能够直接实现dao就能够了,详细实现例如以下:

详细的项目结构例如以下图所看到的:

技术分享

1.改动web.xml来进行spring和pringmvc的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
	
	<!-- log4j配置文件 -->
	<context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:/config/log4j.properties</param-value>
    </context-param>
	
	<!-- Spring的log4j监听器 -->
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>
	
	
	<!--配置參数 和详细项目没有关系 在容器初始化项目还没有启动运行-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:/config/*.xml
		</param-value>
	</context-param>
	<!-- 维护ioc  -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<!-- 能够使用RequestContextHolder.currentRequestAttributes() 获取到请求的attr -->
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    
	<!-- 前端核心分发器 -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!--业务控制器配置文件 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:/config/spring-mvc-servlet.xml</param-value>
		</init-param>
		<load-on-startup>2</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<!-- 
		<url-pattern>*.do</url-pattern>
		 -->
		 <!-- 配置为/ 不带文件后缀,会造成其他静态文件(js。css等)不能訪问。如配为*.do,则不影响静态文件的訪问 -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!-- pushlet 推送 
    <servlet>
        <servlet-name>pushlet</servlet-name>
        <servlet-class>
            nl.justobjects.pushlet.servlet.Pushlet
        </servlet-class>
        <load-on-startup>3</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>pushlet</servlet-name>
        <url-pattern>/pushlet.srv</url-pattern>
    </servlet-mapping>
    -->
	<!-- 字符集 过滤器  -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
	
	<error-page>
		<error-code>500</error-code>
		<location>/500.html</location>
	</error-page>
	<error-page>
		<error-code>404</error-code>
		<location>/404.html</location>
	</error-page>
	
</web-app>

2.配置config包下的applicationContext.xml的内容,这个xml文件包括了全部关于spring的配置。

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://www.springframework.org/schema/jee 
		http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
	default-lazy-init="false">
	<!-- 载入properties文件到spring中。方便在spring中使用 -->
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:/config/jdbc.properties</value>
			</list>
		</property>
	</bean>

	<!-- 使用jdbc来链接数据库。创建数据源 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="${connection.driverClassName}" />
		<property name="url" value="${connection.url}" />
		<property name="username" value="${connection.username}" />
		<property name="password" value="${connection.password}" />
		<property name="maxActive" value="${connection.maxActive}" />
		<property name="maxIdle" value="${connection.maxIdle}" />
		<property name="minIdle" value="${connection.minIdle}" />
		<property name="removeAbandoned" value="${connection.removeAbandoned}" />
		<property name="removeAbandonedTimeout" value="${connection.removeAbandonedTimeout}" />
		<property name="logAbandoned" value="${connection.logAbandoned}" />
		<property name="defaultAutoCommit" value="${connection.defaultAutoCommit}" />
		<property name="defaultReadOnly" value="${connection.defaultReadOnly}" />
	</bean>

	<!--配置事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>


	<!-- 这里我在原来博文的基础上增加了spring的aop事务管理 -->
	<aop:config>
		<!-- 设置pointCut表示哪些方法要增加事务处理 -->
		<!-- 以下的事务是声明在DAO中。可是通常都会在Service来处理多个业务对象逻辑的关系。注入删除,更新等。此时假设在运行了一个步骤之后抛出异常 
			就会导致数据不完整,所以事务不应该在DAO层处理,而应该在service,这也就是Spring所提供的一个很方便的工具,声明式事务 -->
		<aop:pointcut id="txPointcut"
			expression="execution(* com.mpc.*.service..*.*(..))" />
		<!-- 通过advisor来确定详细要增加事务控制的方法 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
	</aop:config>
	<!-- 配置哪些方法要增加事务控制 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="get*" propagation="REQUIRED" read-only="true" />
			<tx:method name="count*" propagation="REQUIRED" read-only="true" />
			<tx:method name="find*" propagation="REQUIRED" read-only="true" />
			<tx:method name="list*" propagation="REQUIRED" read-only="true" />
			<tx:method name="*" propagation="REQUIRED" read-only="true" />
			<!-- 一下方法都是可能设计改动的方法,无法设置为仅仅读 -->
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="create*" propagation="REQUIRED" />
			<tx:method name="insert*" propagation="REQUIRED" />
			<tx:method name="merge*" propagation="REQUIRED" />
			<tx:method name="del*" propagation="REQUIRED" />
			<tx:method name="remove*" propagation="REQUIRED" />
			<tx:method name="put*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="save*" propagation="REQUIRED" />
			<!-- 这个hhh是我測试在aop事务和mybatis配合的时候,事务是否生效 -->
			<tx:method name="hhh*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>



	<!-- 以下是mybatis的相关配置。这些都须要导入jar包,mybaits-spring.jar,这个在我參考的博文中有,我就不多说了 -->


	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!--dataSource属性指定要用到的连接池 -->
		<property name="dataSource" ref="dataSource" />
		<!--configLocation属性指定mybatis的核心配置文件 -->
		<property name="configLocation" value="classpath:/config/Configuration.xml" />
		<!-- 这里指定了我们的User.xml这类规定数据库操作的xml文件的位置。在项目中独立把他们放到了一个mapper包下 -->
		<property name="mapperLocations" value="classpath*:com/mpc/mybaits/mapper/*.xml" />
	</bean>
	<!-- 这个就是用接口变成的方式中,指定从哪里扫描我们的接口,托管到spring中管理,这样在spring的service或dao中就能够使用了 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.mpc.mybaits.inter" />
	</bean>



	<!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
		sqlSessionFactory属性指定要用到的SqlSessionFactory实例 <property name="sqlSessionFactory" 
		ref="sqlSessionFactory" /> mapperInterface属性指定映射器接口,用于实现此接口并生成映射器对象 <property 
		name="mapperInterface" value="com.mpc.mybaits.inter.IUserOperation" /> </bean> -->

	<context:component-scan base-package="com.mpc.mybaits">
	<!-- 注意在这里扫描的时候不要扫描controller,由于在这里装载了controller的话 controller获得的service和dao就是没有事务的-->
		<context:exclude-filter type="annotation"
			expression="org.springframework.stereotype.Controller" />
		<!-- secuirty模块须要 -->
		<context:exclude-filter type="annotation"
			expression="org.springframework.web.bind.annotation.ControllerAdvice" />
	</context:component-scan>
</beans>
3.配置config下的spring-mvc-servlet.xml,这xml文件是用来配置springmvc的,主要包含视图的解析以及相关请求的配置

<?

xml version="1.0" encoding="UTF-8"?

> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd" default-lazy-init="false"> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> <!-- 默认的视图解析器 --> <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="3"> <!-- 假设使用freemaker 或者velocity 须要更改viewClass --> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="contentType" value="text/html" /> <property name="prefix" value="/WEB-INF/view/" /> <property name="suffix" value=".jsp" /> </bean> <!-- 开启controller注解支持 --> <!-- 注:假设base-package=com.mpc 则注解事务不起作用 TODO 读源代码 --> <context:component-scan base-package="com.mpc.mybaits" use-default-filters="false"> <!-- 在这里扫描controller,controller就能获得有事务的service和dao --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <!-- security 模块须要 --> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> </context:component-scan> <!-- 开启注解 --> <mvc:annotation-driven /> <!-- 在配置为/的时候。静态文件的訪问会有问题,配置了这个以后,就不会有问题了 --> <mvc:default-servlet-handler /> </beans>


4.config下的Configuration.xml,这个就是我们的mybatis的核心配置文件,是session的配置信息,因为非常多功能托管给了spring,所以变的非常瘦小

<?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>
	<typeAliases>
		<typeAlias alias="User" type="com.mpc.mybaits.model.User" />
		<typeAlias alias="Article" type="com.mpc.mybaits.model.Article" />
	</typeAliases>



	<!-- 数据源的相关配置已经托管给了spring -->
	<!-- <environments default="development"> <environment id="development"> 
		<transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" 
		value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybaits" 
		/> <property name="username" value="root" /> <property name="password" value="root" 
		/> </dataSource> </environment> </environments> -->
	<!-- mappers的配置托管给了spring -->
	<!-- <mappers> <mapper resource="com/mpc/mybaits/model/User.xml" /> </mappers> -->
</configuration>

5.DAO层的实现

package com.mpc.mybaits.dao;

import java.util.List;

import com.mpc.mybaits.model.Article;
import com.mpc.mybaits.model.User;

public interface UserDAO {
	public List<Article> getUserArticles(int userid);

	public User hhhh(User user);
}


package com.mpc.mybaits.dao.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Repository;

import com.mpc.mybaits.dao.UserDAO;
import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.Article;
import com.mpc.mybaits.model.User;

//规定这个是dao层的组件
@Repository
public class UserDaoImpl implements UserDAO {

	// 注入我们在inter中实现的接口
	@Resource
	private IUserOperation iUserOperation;

	@Override
	public List<Article> getUserArticles(int userid) {
		// 通过在dao中直接使用我们在inter中实现的接口就能够在遵循spring的规范来使用mybaits了
		return iUserOperation.getUserArticles(userid);
	}

	@Override
	public User hhhh(User user) {

		iUserOperation.addUser(user);
		return user;
	}

}

6.service层的实现
package com.mpc.mybaits.service;

import java.util.List;

import com.mpc.mybaits.model.Article;
import com.mpc.mybaits.model.User;

public interface UserService {
	public List<Article> getUserArticles(int userid);

	public User hhhh(User user);
}

package com.mpc.mybaits.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.mpc.mybaits.dao.UserDAO;
import com.mpc.mybaits.model.Article;
import com.mpc.mybaits.model.User;
import com.mpc.mybaits.service.UserService;

@Service
public class UserServiceImpl implements UserService {
	@Resource
	private UserDAO userDao;

	@Override
	public List<Article> getUserArticles(int userid) {
		return userDao.getUserArticles(userid);
	}

	@Override
	public User hhhh(User user) {
		// TODO Auto-generated method stub
		return userDao.hhhh(user);
	}

}

7.controller层的实现

package com.mpc.mybaits.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mpc.mybaits.inter.IUserOperation;
import com.mpc.mybaits.model.Article;
import com.mpc.mybaits.model.User;
import com.mpc.mybaits.service.UserService;
import com.mpc.mybaits.utils.PageInfo;

/**
 * @author Administrator
 *
 */
@Controller
@RequestMapping("/article")
public class UserController {


	@Resource
	UserService userService;



	@RequestMapping("/listspring")
	@ResponseBody
	public List<Article> listallSpring(HttpServletRequest request,
			HttpServletResponse response) {

		List<Article> articles = userService.getUserArticles(1);
		return articles;

	}}

8.启动项目,測试结果:

技术分享

mybatis实战教程(mybatis in action)之七:实现mybatis分页

1.依照我參考的博文的相关内容给util包中加入PageInfo、PagePlugin、ReflectHelper这三个类以后。就给代码中加入了分页插件。

2.在user.xml中加入例如以下代码

	<!-- 分页查询測试 -->
	<select id="selectArticleListPage" resultMap="resultUserArticleList">
		select
		user.id,user.userName,user.userAddress,article.id
		aid,article.title,article.content from user,article
		where
		user.id=article.userid and user.id=#{userid}
	</select>

3.给inter包的接口中加入对应的方法

	public List<Article> selectArticleListPage(@Param("page") PageInfo page,
			@Param("userid") int userid);
4.在Configuration.xml中加入插件

	<plugins>
		<plugin interceptor="com.mpc.mybaits.utils.PagePlugin">
			<property name="dialect" value="mysql" />
			<property name="pageSqlId" value=".*ListPage.*" />
		</plugin>
	</plugins>
这样全部包括ListPage的mapper中的方法都会运行分页动作。

5.在controller中加入例如以下方法測试

	@RequestMapping("/listpage")
	public @ResponseBody List<Article> listpage(HttpServletRequest request,
			HttpServletResponse response) {
		int currentPage = (request.getParameter("page") == null || Integer
				.parseInt(request.getParameter("page")) <= 0) ?

1 : Integer .parseInt(request.getParameter("page")); int pageSize = 2; int currentResult = (currentPage - 1) * pageSize; System.out.println(request.getRequestURI()); System.out.println(request.getQueryString()); PageInfo info = new PageInfo(); info.setShowCount(pageSize); info.setCurrentResult(currentResult); List<Article> list = userMapper.selectArticleListPage(info, 1); System.out.println(info); int totalCount = info.getTotalResult(); int lastPage = 0; if (totalCount % pageSize == 0) { lastPage = totalCount / pageSize; } else { lastPage = 1 + totalCount / pageSize; } if (currentPage >= lastPage) { currentPage = lastPage; } String pageStr = ""; // pageStr = String.format( // "<a href=\"%s\">上一页</a> <a href=\"%s\">下一页</a>", // request.getRequestURI() + "?page=" + (currentPage - 1), // request.getRequestURI() + "?

page=" + (currentPage + 1)); // // ModelAndView mav = new ModelAndView("list"); // mav.addObject("articles", list); // mav.addObject("pageStr", pageStr); // return mav; return list; }


6.測试结果

我规定的是一页显示两条。查询结果例如以下:

技术分享

确实是两条,而我的数据库中有3条数据的。

mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句(这部分貌似和分页一样··没有自己的一些感觉,仅仅是在照猫画虎的学习一些语法来完毕动态语句,參照的博客原文中介绍的都非常具体了,这里我仅仅是想记录一下自己足迹。不爱的同学能够跳过这一段)

1.mybatis if语句处理

在User.xml中加入例如以下代码,用来測试if语句

	<select id="selectUsersInCondition" parameterType="User"
		resultMap="resultListUser">
		select * from user where
		<if test="userAge !=null">
			userAge=#{userAge}
		</if>
		<!-- 自己改动改动··由于假设传入的userAge是null的话,语句就变成了 and userAddress=xxxx,所以多了些推断,往后才知道·原来这样的不靠谱的情况有其它解决方案 -->
		<if test="userAddress !=null and userAge!=null">
			and userAddress=#{userAddress}
		</if>
		<if test="userAddress !=null and userAge==null">
			userAddress=#{userAddress}
		</if>
	</select>

在IUserOperation中加入对应的接口方法

public List<User> selectUsersInCondition(User user);


在controller中加入測试方法

	/**
	 * @return 測试if动态查询
	 */
	@RequestMapping("/listusercon")
	@ResponseBody
	public List<User> listUserCon() {
		User user = new User();

		// user.setUserAge("100");
		user.setUserAddress("shanghai,pudong");
		return userMapper.selectUsersInCondition(user);

	}

測试结果

技术分享
2.choose (when,otherwize)仅仅走当中一条路

在User.xml中加入例如以下代码

	<select id="dynamicChooseTest" parameterType="User" resultMap="resultListUser">
		select * from user where
		<choose>
			<when test="userAddress != null">
				userAddress=#{userAddress}
			</when>
			<when test="userAge != null">
				userAge = #{userAge}
			</when>
			<otherwise>
				id=1
			</otherwise>
		</choose>
	</select>

当传如的user对象的userAddress不为空就依据userAddress查询,userAge不为空就依据userAge查询,otherwise在全部的when都不满足的时候生效。

可是永远仅仅能选一个。

在IUserOperation中加入例如以下语句

public List<User> dynamicChooseTest(User user);
測试方法

	@RequestMapping("/listuserwhere")
	@ResponseBody
	public List<User> listUserWhere() {
		User user = new User();
		// user.setUserAge("100");
		// user.setUserAddress("shanghai,pudong");
		return userMapper.dynamicChooseTest(user);
	}

測试结果

技术分享
能够看到的是在userAge,userAddress都为空的情况下。依据id=1来查询的

3.trim (对包括的内容加上 prefix,或者 suffix 等。前缀。后缀)

trim的作用就是能够为<trim></trim>标签所包括的内容加上一个前缀或者后缀,而且能够指定这个前缀或者后缀覆盖住指定的字符串。

在User.xml中加入例如以下代码

	<select id="dynamicTrimTest" parameterType="User" resultMap="resultListUser">
		select * from user
		<trim prefix="where" prefixOverrides="and |or">
			<if test="userAge != null">
				and userAge = #{userAge}
			</if>
			<if test="userAddress != null">
				and userAddress = #{userAddress}
			</if>
		</trim>
	</select>
这样写的话,就算是userAge不是空的,那么出如今where后面的也是 userAge=xxx不是and userAge=xxx;

在IUserOperation中加入相应的接口方法;

public List<User> dynamicTrimTest(User user);

測试方法

	@RequestMapping("/listusertrim")
	@ResponseBody
	public List<User> listUserTrim() {
		User user = new User();
		// user.setUserAge("110");
		user.setUserAddress("shanghai,pudong");
		return userMapper.dynamicTrimTest(user);
	}

測试结果

技术分享

能够看到。并没有报sql语句错误,trim是成功的。

4. where (主要是用来简化sql语句中where条件推断的,能智能的处理 and or 条件)

个人理解就是<where> ====<trim prefix="where" prefixOverrides="and |or">

在User.xml中加入例如以下代码

	<select id="dynamicWhereTest" parameterType="User" resultMap="resultListUser">
		select * from user
		<where>
			<if test="userAge != null">
				and userAge = #{userAge}
			</if>
			<if test="userAddress != null">
				and userAddress = #{userAddress}
			</if>
		</where>
	</select>

在IUserOperation中加入相应的接口方法

public List<User> dynamicWhereTest(User user);

測试方法:

	@RequestMapping("/listuserauto")
	@ResponseBody
	public List<User> listUserAuto() {
		User user = new User();
		// user.setUserAge("110");
		user.setUserAddress("shanghai,pudong");
		return userMapper.dynamicWhereTest(user);
	}

測试结果

技术分享


5.set (主要用于更新时)

在User.xml中加入例如以下代码

	<update id="dynamicSetTest" parameterType="User">
		update user
		<set>
			<if test="userAge != null">
				userAge = #{userAge},
			</if>
			<if test="userAddress != null">
				userAddress = #{userAddress},
			</if>
		</set>
		where id = #{id}
	</update>
<set>能够智能处理最后一个多出来的逗号

在IUserOperation中加入相应的接口方法

public void dynamicSetTest(User user);

測试方法

	@RequestMapping("/dynamicSetTest")
	@ResponseBody
	public User dynamicSetTest() {
		User user = new User();
		user.setId(1);
		user.setUserAge("120");
		user.setUserAddress("shanghai,pudong,laolao");
		userMapper.dynamicSetTest(user);
		return user;
	}


6. foreach (在实现 mybatis in 语句查询时特别实用) 

6.1但參数List类型

在User.xml中的配置内容例如以下:

	<select id="dynamicForeachTest" resultMap="resultUserArticleList">
		select
		user.id,user.userName,user.userAddress,user.userAge,article.id
		aid,article.title,article.content from user,article
		where
		user.id=article.userid and article.userid in
		<foreach collection="list" index="index" item="item" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>

在IUserOperation中加入相应的接口方法

public List<Article> dynamicForeachTest(List<Integer> ids);
測试方法

	@RequestMapping("/dynamicForeachTest")
	@ResponseBody
	public List<Article> dynamicForeachTest() {
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(3);
		return userMapper.dynamicForeachTest(list);
	}

測试结果

技术分享

6.2数组类型的參数

在User.xml加入例如以下代码

	<select id="dynamicForeach2Test" resultMap="resultUserArticleList">
		select
		user.id,user.userName,user.userAddress,user.userAge,article.id
		aid,article.title,article.content from user,article
		where
		user.id=article.userid and article.userid in
		<foreach collection="array" index="index" item="item" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>

在IUserOperation中加入相应的接口方法

public List<Article> dynamicForeach2Test(int[] ids);

測试方法

	@RequestMapping("/dynamicForeach2Test")
	@ResponseBody
	public List<Article> dynamicForeach2Test() {
		int[] ints = new int[] { 1, 3 };
		return userMapper.dynamicForeach2Test(ints);
	}

測试结果

技术分享

仅仅是查询參数用数组来传入了。查询结果和list传入參数的结果是一样的

6.3map类型的參数,用map类型的參数能够传入多个參数。当中一个用来迭代

在User.xml中加入例如以下代码,使用map来传递參数,那么參数的key值是非常实用的,通过id这个key来获得id的value值,通过指定collection为ids,从而迭代ids这个key所指定的value值。

	<select id="dynamicForeach3Test" resultMap="resultUserArticleList">
		select
		user.id
		uid,user.userName,user.userAddress,user.userAge,article.id
		aid,article.title,article.content from user,article
		where
		article.userid=#{id}
		and user.id=article.userid and article.userid in
		<foreach collection="ids" index="index" item="item" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>

在IUserOperation中加入相应的接口方法

public List<Article> dynamicForeach3Test(Map<String, Object> params);

測试方法

	@RequestMapping("/dynamicForeach3Test")
	@ResponseBody
	public List<Article> dynamicForeach3Test() {
		Map<String, Object> map = new HashMap<String, Object>();
		int[] ints = new int[] { 1, 3 };
		map.put("id", 1);
		map.put("ids", ints);
		return userMapper.dynamicForeach3Test(map);
	}

測试结果

技术分享

mybatis实战教程(mybatis in action)之九:mybatis 代码生成工具的使用

这方面的内容依照參考博客中大神的方法,把各种信息本地化成自己的,就直接执行程序后。我们的各种类和xml文件就自己主动生成到自己的包里了。这里我就不烦人了。


总结:通过參照高手的博客,能够说对mybatis有了一个非常基础的入门,知道了主要的使用技能。非常多的使用技巧和高级的用法在以后项目的实践中还须要自己慢慢的积累和摸索。

























































































以上是关于mybatis自己学习的一些总结的主要内容,如果未能解决你的问题,请参考以下文章

mybatis学习日志二

Mybatis 学习笔记总结

markdown [mybatis参考]关于mybatis #mybatis的一些片段

mybatis学习(39):动态sql片段

Mybatis学习小记

Java习惯用法总结