myBatis实例

Posted 风中男子

tags:

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

1. myBatis的介绍:
		MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除
	了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索。MyBatis可以使用简单的
	XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的
	Java对象)映射成数据库中的记录。
	
	jdbc-->dbutil-->(mybatis)-->hibernate
	
2. mybatis快速入门
	a. 添加jar包
		mybatis
			asm-3.3.1.jar
			cglib-2.2.2.jar
			commons-logging-1.1.1.jar
			log4j-1.2.16.jar
			mybatis-3.1.1.jar
			slf4j-api-1.6.2.jar
			slf4j-log4j12-1.6.2.jar
		mysql驱动
			mysql-connector-java-5.1.7-bin.jar
		
	b. 建库+表
		create database mybatis;
		use mybatis;
		CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT);
		INSERT INTO users(NAME, age) VALUES(‘Tom‘, 12);
		INSERT INTO users(NAME, age) VALUES(‘Jack‘, 11);
	c. 在应用的src下添加Mybatis的配置文件conf.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>
			<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://localhost:3306/mybatis" />
						<property name="username" value="root" />
						<property name="password" value="root" />
					</dataSource>
				</environment>
			</environments>
		</configuration>
		
	d. 定义表所对应的实体类
		public class User {
			private int id;
			private String name;
			private int age;
		}
	e. 定义操作users表的sql映射文件userMapper.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="org.mybatis.example.BlogMapper"> 
			<select id="selectBlog" parameterType="int" resultType="Blog"> 
				select * from Blog where id = #{id} 
			</select> 
		</mapper>
	f. 在conf.xml文件中注册userMapper.xml文件
		<mappers>
			<mapper resource="com/atguigu/day03_mybatis/test1/userMapper.xml"/>
		</mappers>
	g. 编写测试代码:执行定义的select语句
		public class Test {
			public static void main(String[] args) throws IOException {
				String resource = "conf.xml"; 
				//加载mybatis的配置文件(它也加载关联的映射文件)
				Reader reader = Resources.getResourceAsReader(resource); 
				//构建sqlSession的工厂
				SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
				//创建能执行映射文件中sql的sqlSession
				SqlSession session = sessionFactory.openSession();
				//映射sql的标识字符串
				String statement = "net.lamp.java.mybatis.bean.userMapper"+".selectUser";
				//执行查询返回一个唯一user对象的sql
				User user = session.selectOne(statement, 1);
				System.out.println(user);
			}
		}
	
3. 编写基于mybatis的操作users表的CRUD操作的dao类
	a. XML的实现:
		1. 定义sql映射xml文件:
			<insert id="insertUser" parameterType="net.lamp.java.ibatis.bean.User">
				insert into users(name, age) values(#{name}, #{age});
			</insert>
			
			<delete id="deleteUser" parameterType="int">
				delete from users where id=#{id}
			</delete>
			
			<update id="updateUser" parameterType="net.lamp.java.ibatis.bean.User">
				update users set name=#{name},age=#{age} where id=#{id}
			</update>
			
			<select id="selectUser" parameterType="int" resultType="net.lamp.java.ibatis.bean.User">
				select * from users where id=#{id}
			</select>
			
			<select id="selectAllUsers" resultType="net.lamp.java.ibatis.bean.User">
				select * from users
			</select>
		2. 在config.xml中注册这个映射文件
			<mapper resource="net/lamp/java/ibatis/bean/userMapper.xml"/>
		3. 在dao中调用:
			public User getUserById(int id) {
		
				SqlSession session = sessionFactory.openSession();
				User user = session.selectOne(URI+".selectUser", id);
				return user;
			}
	b. 注解的实现:
		1. 定义sql映射的接口
			public interface UserMapper {

				@Insert("insert into users(name, age) values(#{name}, #{age})")
				public int insertUser(User user);

				@Delete("delete from users where id=#{id}")
				public int deleteUserById(int id);
				
				@Update("update users set name=#{name},age=#{age} where id=#{id}")
				public int updateUser(User user);

				@Select("select * from users where id=#{id}")
				public User getUserById(int id);

				@Select("select * from users")
				public List<User> getAllUser();
			}
		2. 在config中注册这个映射接口
			<mapper class="net.lamp.java.ibatis.crud.ano.UserMapper"/>
		3. 在dao类中调用
			public User getUserById(int id) {
				SqlSession session = sessionFactory.openSession();
				UserMapper mapper = session.getMapper(UserMapper.class);
				User user = mapper.getUserById(id);
				return user;
			}
	
4. 几个可以优化的地方
	a. 连接数据库的几个配置可以单独放在一个properties文件中
		db.properties
		
		<properties resource="db.properties"/>
		
		<property name="driver" value="${driver}" />
		<property name="url" value="${url}" />
		<property name="username" value="${username}" />
		<property name="password" value="${password}" />
		
	b. 为实体类定义别名,简化sql映射xml文件中的引用
		<typeAliases>
			<typeAlias type="net.lamp.java.ibatis.bean.User" alias="_User"/>
		</typeAliases>
	c. 可以在src下加入log4j的配置文件,打印日志信息(主要是sql语句)
		1. log4j.properties
			log4j.properties,
			log4j.rootLogger=DEBUG, Console
			#Console
			log4j.appender.Console=org.apache.log4j.ConsoleAppender
			log4j.appender.Console.layout=org.apache.log4j.PatternLayout
			log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
			log4j.logger.java.sql.ResultSet=INFO
			log4j.logger.org.apache=INFO
			log4j.logger.java.sql.Connection=DEBUG
			log4j.logger.java.sql.Statement=DEBUG
			log4j.logger.java.sql.PreparedStatement=DEBUG
		2. log4j.xml
			<?xml version="1.0" encoding="UTF-8" ?>
			<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
			<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
				<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
					<layout class="org.apache.log4j.PatternLayout">
						<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) \n" />
					</layout>
				</appender>
				<logger name="java.sql">
					<level value="debug" />
				</logger>
				<logger name="org.apache.ibatis">
					<level value="debug" />
				</logger>
				<root>
					<level value="debug" />
					<appender-ref ref="STDOUT" />
				</root>
			</log4j:configuration>
		
5. 解决表的字段名与实体类的属性名不相同的冲突
	a. 准备表和数据:
		CREATE TABLE orders(
			order_id INT PRIMARY KEY AUTO_INCREMENT,
			order_no VARCHAR(20), 
			order_price FLOAT
		);
		INSERT INTO orders(order_no, order_price) VALUES(‘aaaa‘, 23);
		INSERT INTO orders(order_no, order_price) VALUES(‘bbbb‘, 33);
		INSERT INTO orders(order_no, order_price) VALUES(‘cccc‘, 22);
			
	b. 定义实体类:
		public class Order {
			private int id;
			private String orderNo;
			private float price;
		}
	c. 实现getOrderById(id)的查询
		c1. 通过在sql语句中定义别名
			<select id="selectOrder" parameterType="int" resultType="_Order">
				select order_id id, order_no orderNo,order_price price from orders where order_id=#{id}
			</select>
			
		c2. 定义<resultMap>
			<select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap">
				select * from orders where order_id=#{id}
			</select>
			
			<resultMap type="_Order" id="orderResultMap">
				<id property="id" column="order_id"/>
				<result property="orderNo" column="order_no"/>
				<result property="price" column="order_price"/>
			</resultMap>
	
6. 实现联表查询
	1). 一对一:
		a. 创建表和数据:
			CREATE TABLE teacher(
				t_id INT PRIMARY KEY AUTO_INCREMENT, 
				t_name VARCHAR(20)
			);
			CREATE TABLE class(
				c_id INT PRIMARY KEY AUTO_INCREMENT, 
				c_name VARCHAR(20), 
				teacher_id INT
			);
			ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teacher(t_id);	

			INSERT INTO teacher(t_name) VALUES(‘LS1‘);
			INSERT INTO teacher(t_name) VALUES(‘LS2‘);

			INSERT INTO class(c_name, teacher_id) VALUES(‘bj_a‘, 1);
			INSERT INTO class(c_name, teacher_id) VALUES(‘bj_b‘, 2);
		b. 定义实体类:
			public class Teacher {
				private int id;
				private String name;
			}
			public class Classes {
				private int id;
				private String name;
				private Teacher teacher;
			}
		c. 定义sql映射文件ClassMapper.xml:
			<!-- 方式一:嵌套查询方式, 通过执行另外一个SQL映射语句来返回预期的复杂类型 -->
			<select id="getClasses" parameterType="int" resultMap="ClassesResultMap2">
				select * from class where c_id=#{id}
			</select>
			
			<resultMap type="CLasses" id="ClassesResultMap2">
				<id column="c_id" property="id"/>
				<result column="c_name" property="name"/>
				<association property="teacher" javaType="Teacher" column="teacher_id" select="getTeacher"></association>
			</resultMap>
			
			<select id="getTeacher" parameterType="int" resultType="Teacher">
				select t_id id, t_name name from teacher where t_id=#{id}
			</select>
				
			<!-- 
				方式二:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
			 -->
			 <select id="getClasses2" parameterType="int" resultMap="ClassesResultMap">
					select * from class c,teacher t where c.c_id=#{id} and c.teacher_id=t.t_id; 
			</select>
			
			<resultMap type="Classes" id="ClassesResultMap">
				<id column="c_id" property="id"/>
				<result column="c_name" property="name"/>
				<association column="teacher_id" property="teacher" javaType="Teacher">
					<id column="t_id" property="id"/>
					<result column="t_name" property="name"/>
				</association>
			</resultMap>
		d. 测试:
			@Test
			public void testQueryOO() {
				SqlSession session = factory.openSession();
				Classes c = sqlSession.selectOne("com.atguigu.day03_mybatis.test5.CTMapper.getClasses", 1);
				System.out.println(c);
			}
			
			@Test
			public void testQueryOO2() {
				SqlSession session = factory.openSession();
				Classes c = sqlSession.selectOne("com.atguigu.day03_mybatis.test5.CTMapper.getClasses2", 1);
				System.out.println(c);
			}
	2) 一对多
		a. 创建表和数据:
			CREATE TABLE student(
				s_id INT PRIMARY KEY AUTO_INCREMENT, 
				s_name VARCHAR(20), 
				class_id INT
			);
			INSERT INTO student(s_name, class_id) VALUES(‘xs_B‘, 1);
			INSERT INTO student(s_name, class_id) VALUES(‘xs_D‘, 1);
			INSERT INTO student(s_name, class_id) VALUES(‘xs_E‘, 1);
			INSERT INTO student(s_name, class_id) VALUES(‘xs_A‘, 2);
			INSERT INTO student(s_name, class_id) VALUES(‘xs_H‘, 2);
			INSERT INTO student(s_name, class_id) VALUES(‘xs_J‘, 2);
		b. 定义实体类:
			public class Student {
				private int id;
				private String name;
			}
			
			public class Classes {
				private int id;
				private String name;
				private Teacher teacher;
				private List<Student> students;
			}
		
		c. 定义sql映射文件ClassMapper.xml:(根据classId查询对应的班级信息,包括学生)
			<!-- 集合的嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集-->
			 <select id="getClasses3" parameterType="int" resultMap="ClassesResultMap3">
					select * from class c,teacher t, student s where c.c_id=#{id} and c.teacher_id=t.t_id and s.class_id=c.c_id 
			</select>
			
			<resultMap type="Classes" id="ClassesResultMap3">
				<id column="c_id" property="id"/>
				<result column="c_name" property="name"/>
				<association column="teacher_id" property="teacher" javaType="Teacher">
					<id column="t_id" property="id"/>
					<result column="t_name" property="name"/>
				</association>
				<collection property="students" ofType="Student" javaType="ArrayList">
					<id property="id" column="s_id" />
					<result property="name" column="s_name"/>
				</collection>
			</resultMap>
			
			<!-- 集合的嵌套查询方式, 通过执行另外一个SQL映射语句来返回预期的复杂类型 -->
			<select id="getClasses4" parameterType="int" resultMap="ClassesResultMap4">
					select * from class c where c.c_id=#{id}
			</select>
			<resultMap type="CLasses" id="ClassesResultMap4">
				<id column="c_id" property="id"/>
				<result column="c_name" property="name"/>
				<association property="teacher" javaType="Teacher" column="teacher_id" select="getTeacher"></association>
				<collection property="students" ofType="Teacher" column="c_id" select="getStudentsSelect" ></collection>
			</resultMap>
			
			<select id="getTeacher" parameterType="int" resultType="Teacher">
				select t_id id, t_name name from teacher where t_id=#{id}
			</select>
			<select id="getStudentsSelect" parameterType="int" resultType="Student" >
				select s_id id, s_name name from student where class_id=#{id}
			</select>
		d. 测试:
			@Test
			public void testQueryOT() {
				SqlSession session = factory.openSession();
				Classes classes = openSession.selectOne("com.atguigu.day03_mybatis.test6.OMMapper.getClasses3", 1);
				System.out.println(c);
			}
			
			@Test
			public void testQueryOT2() {
				SqlSession session = factory.openSession();
				Classes classes = openSession.selectOne("com.atguigu.day03_mybatis.test6.OMMapper.getClasses4", 1);
				System.out.println(c);
			}

以上是关于myBatis实例的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis之Mapper XML 文件详解-sql和入参

片段事务中的实例化错误

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

mybatis 动态SQL .2

mybatis 详解------动态SQL

mybatis 详解------动态SQL