您的位置:首页 > 其它

MyBatis学习记录-01

2016-04-29 15:57 393 查看
MyBatis是一个十分重要的持久层框架,在电商系统中应用广泛;今将Mybatis的学习经历记录如下;

MyBatis介绍

MyBatis框架原理

基础入门

映射文件的配置(包括动态SQL,输出映射以及输入映射)

MyBatis以及Hibernate技术选型要点与比较

1、MyBatis介绍

mybatis是一个对于JDBC进行封装的持久层框架。MyBatis框架的前身是ibatis。它在配置文件中编写sql,项目中真正的需求落实到实处就是数据库的操作,而mybatis就是专门用来直接编写sql来确保业务需求的完成。它可以对输入参数输出结果与java类型进行映射。它是不完整的orm映射框架。而正是因为以上的原因MyBatis的应用在业务需求灵活多变的公司以及项目上应用十分的广泛,比如在电商淘宝等项目上的应用。

MyBatis与JDBC的对比,JDBC中存在的问题

首先看一份最简单的JDBC代码:

// JDBC代码片段
public static void main(String[] args) throws SQLException {
//数据库连接
Connection connection = null;
//预编译statement
//好处:防止 sql注入,提高数据的性能
PreparedStatement preparedStatement = null;
//结果集
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//连接数据库
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis", "root", "1234");
//定义sql语句,根据名称查询用户表的记录
String sql = "SELECT * FROM USER WHERE username =  ?";
//构造preparedStatement
preparedStatement = connection.prepareStatement(sql);
//向preparedStatement中占位符的位置设置参数
preparedStatement.setString(1, "admin");
//发起数据库查询请求,得到结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果
while(resultSet.next()){
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
Date birthday = resultSet.getDate("birthday");
System.out.println(id+"   "+username+"  "+birthday);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
resultSet.close();
}
if(preparedStatement!=null){
preparedStatement.close();
}
if(connection!=null){
connection.close();
}
}
}


总结:

1、创建连接时存在硬编码;

2、执行statement时存在硬编码;

3、频繁的开闭数据库连接,会影响数据库的性能。

2、MyBatis框架原理图:



3、基础入门

首先是一个比较简单的功能就是实现一个基本的增删改查的功能;

使用工具:Myeclipse、Mysql数据库;

首先创建JAVA工程项目,创建数据库Mybatis;

SQL片段:

CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;


insert  into `user`
(`id`,`username`,`birthday`,`sex`,`address`)
values
(1,'王五',NULL,'2',NULL),(10,'张三','2014-07-10','1','北京市'),
(16,'张小明',NULL,'1','四川省'),(22,'王小明',NULL,'1','四川省'),
(24,'张三丰',NULL,'1','四川省'),(25,'李小明',NULL,'1','四川省'),
(26,'王五',NULL,NULL,NULL);




由于MyBatis没有自带的日志文件系统,所以使用的是log4j的日志文件系统;

log4j.properties日志文件配置如下:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n


数据库相关信息配置db.properties:

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
db.username=root
db.password=1234


SqlMapConfig.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>
<!-- 引用java的配置信息 -->
<properties resource="db.properties" />
<!-- 配置mybatis的环境信息,与spring整合之后,交由spring来管理数据信息 -->
<environments default="development">
<!-- id配置是为了方便数据库的改变的情况的配置,通过更改id就可以实现 -->
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,采用mybatis连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</dataSource>
</environment>
</environments>
<!-- 在sqlMapConfig.xml文件中加载user.xml文件 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<!-- 批量 -->
<!-- <package name="com.mybatis.demo.mapper"/> -->
</mappers>
</configuration>


在config的source folder包下面的配置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">

<!-- namespace的存在是为了保证sql的分类管理 -->
<!-- 重要:namespace在代理模式下开发具有十分重要的作用 -->
<mapper namespace="userDao">
<!-- 根据用户Id查询用户 -->
<!-- select:表示了一个查询的statement -->
<!-- id:表示了该statement的唯一标示 -->
<!-- #{}:表示一个占位符? -->
<!-- parameterType表示的输入参数的Java类型 -->
<select id="findUserByUserId" parameterType="int"
resultType="com.mybatis.demo.po.User">
select * from user where id = #{value}
</select>

<!-- 利用用户名称进行模糊查询 -->
<!-- ${}:表示一个sql的拼接符 -->
<!-- ${value}:${}里面的id表示接受java类型的参数的参数名称,使用${}接受简单类型的时候,里面的值只能够是value -->
<!-- 注意:${}会引起sql的注入,所以一定要慎用 -->
<select id="findUserByName" parameterType="java.lang.String"
resultType="com.mybatis.demo.po.User">
select * from user where username like '%${value}%'
</select>

<!-- 添加用户 -->
<insert id="insertUser" parameterType="com.mybatis.demo.po.User">
insert into user
(username,birthday,sex,address)
values
(#{username},#{birthday},#{sex},#{address})
</insert>

<!-- 添加用户,使用select的方法首先查出主键 -->
<!-- selectKey:可以通过sql查询主键,把主键信息封装到参数的POJO属性上 -->
<!-- LAST_INSERT_ID:mysql的函数,通过它可以查询出主键的id,这个函数必须配合insert语句配合使用 -->
<!-- order:selectKey里面sql的执行顺序,相当于insert语句 -->
<insert id="insertUserId" parameterType="com.mybatis.demo.po.User">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user
(username,birthday,sex,address)
values
(#{username},#{birthday},#{sex},#{address})
</insert>

<!-- 删除用户通过用户ID -->
<delete id="deleteUser" parameterType="int">
DELETE FROM USER WHERE id = #{id}
</delete>

<!-- 删除用户通过用户名称 -->
<delete id="deleteUserName" parameterType="com.mybatis.demo.po.User">
DELETE FROM USER WHERE username = #{username}
</delete>

<!-- 修改用户信息 -->
<update id="updateUser" parameterType="com.mybatis.demo.po.User">
UPDATE USER SET username = #{username},sex = #{sex} where id=#{id}
</update>

</mapper>


增删改查四种方法的初级使用



User_select.java

package com.mybatis.demo.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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.Before;
import org.junit.Test;

import com.mybatis.demo.po.User;

public class User_select {
//全局配置文件地址
private final static String resource = "SqlMapConfig.xml";
//创建SqlSessionFactory对象
private static SqlSessionFactory sessionFactory = null;

@Before
public void config() throws IOException {
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过配置文件创建SqlSessionFactory
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test_select_id() throws Exception {
//通过factory创建session
SqlSession session = sessionFactory.openSession();
//通过select查询User
User user = session.selectOne("userDao.findUserByUserId",1);
System.out.println(user);
//关闭连接
session.close();
}
@Test
public void test_select_name() throws Exception {
//通过factory创建session
SqlSession session = sessionFactory.openSession();
//通过select查询User
List<User> users = session.selectList("userDao.findUserByName","王");
System.out.println(users);
//关闭连接
session.close();
}

}


User_insert.java

package com.mybatis.demo.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

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.Before;
import org.junit.Test;

import com.mybatis.demo.po.User;

public class User_insert {
//全局配置文件地址
private final static String resource = "SqlMapConfig.xml";
//创建SqlSessionFactory对象
private static SqlSessionFactory sessionFactory = null;

@Before
public void config() throws IOException {
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过配置文件创建SqlSessionFactory
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}

@Test
public void test_insert_noId() throws Exception {
//通过factory创建session
SqlSession session = sessionFactory.openSession();
User user = new User();
user.setUsername("admin");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("江苏省南通市");
session.insert("userDao.insertUser", user);
//必须要执行事务
session.commit();
//关闭连接
session.close();
}

@Test
public void test_insert_hasId() throws Exception {
//通过factory创建session
SqlSession session = sessionFactory.openSession();
User user = new User();
user.setUsername("admin");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("江苏省南通市");
session.insert("userDao.insertUserId", user);
//必须要执行事务
session.commit();
//关闭连接
session.close();
}

}


User_insert.java

package com.mybatis.demo.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

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.Before;
import org.junit.Test;

import com.mybatis.demo.po.User;

public class User_delete {
//全局配置文件地址
private final static String resource = "SqlMapConfig.xml";
//创建SqlSessionFactory对象
private static SqlSessionFactory sessionFactory = null;

@Before
public void config() throws IOException {
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过配置文件创建SqlSessionFactory
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}

@Test
public void test_delete() throws Exception {
//通过factory创建session
SqlSession session = sessionFactory.openSession();
User user = new User();
user.setUsername("admin");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("江苏省南通市");
session.delete("userDao.deleteUserName", user);
//必须要执行事务
session.commit();
//关闭连接
session.close();
}
}


User_update.java

package com.mybatis.demo.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

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.Before;
import org.junit.Test;

import com.mybatis.demo.po.User;

public class User_update {
//全局配置文件地址
private final static String resource = "SqlMapConfig.xml";
//创建SqlSessionFactory对象
private static SqlSessionFactory sessionFactory = null;

@Before
public void config() throws IOException {
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过配置文件创建SqlSessionFactory
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}

@Test
public void test_update() throws Exception {
//通过factory创建session
SqlSession session = sessionFactory.openSession();
User user = new User();
user.setId(1);
user.setUsername("admin");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("江苏省南通市");
session.update("userDao.updateUser", user);
//必须要执行事务
session.commit();
//关闭连接
session.close();
}
}


一些用法的区别:

1)parameterType和resultType

parameterType指定输入参数的java类型,可以填写别名或Java类的全限定名。

resultType指定输出结果的java类型,可以填写别名或Java类的全限定名。

2)#{}和${}

#{}:相当于预处理中的占位符?;

#{}:里面的参数表示接收java输入参数的名称;

#{}:可以接受HashMap、简单类型、POJO类型的参数;

当接受简单类型的参数时,#{}里面可以是value,也可以是其他;

#{}可以防止SQL注入;

${}:相当于拼接SQL串,对传入的值不做任何解释的原样输出;

${}会引起SQL注入,所以要谨慎使用;

${}可以接受HashMap、简单类型、POJO类型的参数;

当接受简单类型的参数时,${}里面只能是value;

3)主键生成策略

MySQL可以使用自主主键获取以及调用数据库自身的UUID()函数进行获取

Oracle主键返回策略

Oracle没有自增主键,使用oracle的序列(可以生成流水号,类似 自增主键)生成主键。

通过序列获取流水号方法:

Select 序列名.next.val from dual

4、映射文件的配置(包括动态SQL,输出映射以及输入映射)

知识点一: 这一次使用代理的方式,有两种全局配置方法:



方法一的配置方法与sqlMap包下的User.xml的配置方法大同小异,但是UserMapper放置在src下的mapper包下的方法需要使用

<!-- 批量 -->
<package name="com.mybatis.demo.mapper"/>


UserMapper.java

package com.mybatis.demo.mapper;

import com.mybatis.demo.po.User;

public interface UserMapper {

public User findUserByUserId(int id) throws Exception;

public void insertUser(User user) throws Exception;

}


UserMapper.xml与User.xml内容相同

测试:(UserMapperTest)

package com.mybatis.demo.test;

import java.io.InputStream;

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.Before;
import org.junit.Test;

import com.mybatis.demo.mapper.UserMapper;
import com.mybatis.demo.po.User;

public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;

@Before
public void setUp() throws Exception {
//读取配置文件
InputStream config =
Resources.getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
}

@Test
public void testFindUserById() throws Exception {
SqlSession session = sqlSessionFactory.openSession();

UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.findUserByUserId(1);

System.out.println(user);

session.close();
}
}


知识点二 :重点内容:

定义SQL语句片段,例子如下:

<!-- 定义sql语句片段 -->
<sql id="whereClause">
<if test="user!=null">
<if test="user.sex!=null and user.sex!=''">
AND sex = #{user.sex}
</if>
<if test="user.username!=null and username!=''">
AND username LIKE '%${user.username}'
</if>
</if>

<!-- collection:表示接收到集合参数参数名称 -->
<!-- item:遍历出来的项 -->
<!-- open:遍历开始时要拼接的字符串 -->
<!-- close:遍历结束时要拼接的字符串 -->
<!-- separator:遍历过程中间要拼接的字符串 -->
<if test="idList != null and idList.size > 0">
<foreach collection="idList" item="id" open="AND id IN (" close=")"
separator=",">
#{id}
</foreach>
</if>
</sql>


5、MyBatis与Hibernate的技术选型:(From MyBatis 课程)

Mybatis技术特点:

1、通过直接编写SQL语句,可以直接对SQL进行性能的优化;

2、学习门槛低,学习成本低;

3、由于直接编写SQL语句,所以灵活多变,代码维护性更好。

4、不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。

5、需要编写结果映射。

Hibernate技术特点:

1、标准的orm框架,程序员不需要编写SQL语句。

2、具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。

3、学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。

4、程序员不能自主的去进行SQL性能优化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: