mybatis第一天——入门与概述
大纲摘要:
1、mybatis的介绍
2、Mybatis的入门
a) 使用jdbc操作数据库存在的问题
b) Mybatis的架构
c) Mybatis的入门程序
3、Dao的开发方法
a) 原始dao的开发方法——由ibatis遗留下来的
b) mapper动态代理方式
4、SqlMapConfig.xml文件说明
一、mybatis概述
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
2013年11月迁移到Github。 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,
而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,
并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
是一个不完全的orm框架
根据经典的凡技术必登其官网的结论,官网文档很有必要参阅:http://www.mybatis.org/mybatis-3/zh/index.html
二、mybatis入门
【更新】 问题总结
1、 在创建连接时,存在硬编码
配置文件(全局配置文件)
2、 在执行statement时存在硬编码
配置文件(映射文件)
3、 频繁的开启和关闭数据库连接,会造成数据库性能下降。
数据库连接池(全局配置文件)
很多硬编码,把程序写死了!
1.mybatis架构
详细架构请参见:http://blog.csdn.net/luanlouis/article/details/40422941
//SqlSession本身只是一个接口,它依靠executor进行执行增删改查操作
三.入门程序
导包:在github上下载mybatis,下载地址:
https://github.com/mybatis/mybatis-3/releases
包的结构如下:
导入的包如下图所示:
引入核心jar包以及lib目录的下的依赖包
引入Mysql驱动包(持久层框架需要连接数据库都必须 必须导入驱动包!!!)
引入junit包(eclipse引入方法见另外一篇随笔)
创建核心配置文件——(全局配置文件)
新建一个与src同级的 source folder( maven的目录结构) 新建 SqlMapConfig.xml (约定大于配置,尽量不要修改名称)
(实际开发时会与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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
</configuration>
//ps:每次新建xml文件,第一件事应该是引入约束
引入log4j.properties——这是从官方文档中PDF中拿的(官方文档的查阅有待加强)
# 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
创建POJO类 User.java
package cn.pojo; import java.util.Date; public class User { private int id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]"; } }
创建Sql映射文件 User.xml ——此命名方式是ibatis遗留下来的
<?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隔离 -->
<mapper namespace="test">
<!-- id为SQL:语句唯一标识
parameterType:指定入参类型,java的类型而不是数据库的类型
resultType:指定返回结果集类型(如 POJO类型)
#{}是占位符,起到占位作用(不使用之前的?)#{中的变量名称可以随意写(当然尽量遵循规范)}
-->
<select id="findById" parameterType="java.lang.Integer" resultType="cn.pojo.User">
select * from user where id = #{id}
</select>
<!-- 按姓名查询,
返回的是集合类型 ,resultType里写的是selectList返回的集合里的泛型
${}原样拼接字符 传参是基本数据类型(包括String)里面变量名必须是value
拼接符有SQL注入的风险,慎用 一般like的地方用拼接
-->
<select id="findByName" parameterType="java.lang.String" resultType="cn.pojo.User">
select * from user where username like '%${value}%';
</select>
</mapper>
//一般而言不要直接在映射文件直接写SQL,在navicat等数据库管理工具写完做简单验证后再写回来
无论返回值是单个或者集合,returnType表示的是返回集合时集合泛型里的泛型
加载映射文件
<?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> <!-- 和spring整合后 environments配置将废除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理--> <transactionManager type="JDBC" /> <!-- 数据库连接池(有其他性能更好的连接池,此处暂不展开)--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 引入映射文件 --> <mappers> <mapper resource="User.xml"/> </mappers> </configuration>
查询:
测试函数:
package mybatis01;
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.Test;
import cn.pojo.User;
public class UserTest {
@Test
public void findById() throws Exception{
//通过流将核心配置文件进行读取(注意resources的所在包)
String resource = "SqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//通过核心配置文件输入流来创建工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//通过工厂创建会话
SqlSession session = factory.openSession();
/*执行查询操作
* 第一个参数为SQL语句 namespace+sql语句id格式
* 第二个参数为SQL参数
*/
User user = session.selectOne("test.findById", 1);
System.out.println(user.toString());
session.close();
}
@Test
public void findByName() throws Exception{
String resource = "SqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
List<User> list = session.selectList("test.findByName", "王");
System.out.println(list);
}
}
//通过Resource获取核心配置文件到流里面
SQL模糊匹配规则如下:
% :表示任意0个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。
_ : 表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句:
[ ]([^]同理) :表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。
小结:
1 #{}和${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。
#{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,直接原样输出 ${}可以接收简单类型值或pojo属性值,常用于排序后面的动态列等。
其中,#是表示预编译的SQL,其SQL会在解析时解析为 ?(SELECT * FROM user WHERE id = ?),然后在DBMS阶段进行替换。
$是仅在动态解析SQL时便进行替换,也就是说SQL解析之后均为常量
一般$用于传递表名、字段名、ORDER BY排序字段后等
如果 parameterType传输单个简单类型值,${}括号中只能是value。(防SQL注入见文末今日小结)
类似于一个是state,一个是pstate,占位符就相当于 ?
更多相关见今日小结
2 parameterType和RessultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
3 selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查询一条或多条记录
增加
修改映射文件,增加相关的配置
<!-- insert无返回值类型,入参是整个实体类
入参是POJO类型,#{}中的变量名必须属性,属性,...
-->
<!-- 如果要返回数据库自增主键,可以使用数据库的函数进行查询SELECT LAST_INSERT_ID() -->
<insert id="insertUser" parameterType="cn.pojo.User">
<!-- 执行数据库函数,返回自增主键
keyProperty:将返回的主键保存在入参的user的id里
order:在insert前执行是ibefore 在insert后执行是after
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address})
</insert>
//原理是使用的OGNL对象图导航语言
测试函数:
@Test
public void insert() throws Exception{
String resource = "SqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
User user = new User();
user.setUsername("老李");
//util下的Date
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("北京");
session.insert("test.insertUser", user);
//提交事务(会自动开启事务),必须提交,否则运行成功后数据也无法插入到数据库
session.commit();
//传的是对象的引用,此时get到的是最新的插入的ID,因为通过配置进行了保存
System.out.println(user.getId());
}
//注意事务的部分,增删改需要手动的提交事务!(openSession()的时候默认开启了事务,此方法有重载方法,参数为bool值,可以设置为true以设置不开启事务),不提交是不会更新到数据库的
小结:
添加selectKey实现将主键返回:必须和insert语句一起使用
keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,
所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值
当使用 UUID 作为主键时:需要增加通过select uuid() (函数)得到uuid值
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User"> <selectKey resultType="java.lang.String" order="BEFORE" keyProperty="id"> select uuid() </selectKey> insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address}) </insert>
//注意这里使用的order是“BEFORE”
//此时使用的ID是通过我们生成进行插入的,所以首先需要在插入时显式的指定给ID赋值,因为该ID不是通过自增生成的 (VALUES(#{id}) )
//此时的SELECT UUID()函数会自动将生成的UUID赋值给指定的ID值
//由于接收的是POJO类型,所以#{}里面必须是属性值(注意${}必须是value)
删除
修改映射文件,增加相关的配置
<!-- 删除无返回值,占位符变量可自定义 -->
<delete id="deleteById" parameterType="int">
DELETE FROM user WHERE id = #{id}
</delete>
测试函数:
@Test
public void delete() throws Exception{
String resource = "SqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
session.delete("test.deleteById", 29);
session.commit();
}
//注意事务的提交
修改
修改映射文件,增加相关的配置
<!-- 更新时注意入参是pojo类型,此时占位符变量必须是属性名! -->
<update id="updateById" parameterType="cn.pojo.User">
UPDATE user SET username=#{username} WHERE id=#{id}
</update>
测试函数:
@Test
public void update() throws Exception{
String resource = "SqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
User user = new User();
user.setId(28);
user.setUsername("县长");
//util下的Date
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("北京");
session.delete("test.updateById", user);
session.commit();
}
//注意入参
四、DAO的开发方法
1.原生的开发方式——接口+实现类模式
//也就是将test中的代码进行一些改动,加到Dao
定义接口:
package cn.dao; import java.util.List; import cn.pojo.User; public interface UserDao { User findById(Integer id); List<User> findByUsername(String username); }
定义实现类:
package cn.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import cn.pojo.User;
public class UserDaoImpl implements UserDao {
//构造方法注入factory
private SqlSessionFactory factory;
public UserDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public User findById(Integer id) {
//session是线程不安全的,最佳使用是在方法体内
SqlSession session = factory.openSession();
return session.selectOne("test.findById", id);
}
@Override
public List<User> findByUsername(String username) {
//session是线程不安全的,最佳使用是在方法体内
SqlSession session = factory.openSession();
return session.selectList("test.findByName", username);
}
}
//使用构造方法注入factory的形式,因为不应该频繁地创建工厂,SqlSessionFactory生命周期应该是全局的单例的
//与spring整合后,交给spring来进行管理,所以这里用spring的非常熟悉的依赖注入(这里暂时使用构造注入) (而SqlSession有线程安全问题,无法进行单例的控制)
测试类:
package mybatis01;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.dao.UserDao;
import cn.dao.UserDaoImpl;
import cn.pojo.User;
public class UserDaoTest {
private SqlSessionFactory factory;
//在测试方法前会执行此初始化方法,构造工厂
@Before
public void setUp() throws Exception{
//通过流将核心配置文件进行读取(注意resources的所在包)
String resource = "SqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//通过核心配置文件输入流来创建工厂
factory = new SqlSessionFactoryBuilder().build(in);
}
@Test
public void test1() throws Exception{
UserDao dao = new UserDaoImpl(factory);
User user = dao.findById(1);
System.out.println(user.toString());
}
@Test
public void test2() throws Exception{
UserDao dao = new UserDaoImpl(factory);
List<User> list = dao.findByUsername("王");
System.out.println(list);
}
}
//注意before注解的使用
【更新】:问题引入:
1、 有大量的重复的模板代码——例如获得sqlSession的过程,session的关闭
2、 存在硬编码
硬编码就是一种不够灵活的代码方案。
比如说,一个服务期端的程序,在执行时需要创建服务器进行侦听,你可以简单的将它需要侦听的端口号放在代码里面,
也可以通过程序参数传入,也可以通过配置文件放置。
上述的放在代码里面的就叫做硬编码
所以我们前面说的mapper里的命名空间不能随便写,后面它需要根据这个动态生成编码。前面一些模板代码都是重复的,里面的.selectOnde() .delete()等方法,里面需要传入的参数,第二个SQL参数由方法传入,所以就剩SQL的id,如果我们可以确定这个,那么就能实现了!
2.动态代理Dao的方式——只写接口,不写实现,由mybatis生成
mapper代理使用的是JDK的动态代理
【更新】:
1、 mapper接口的全限定名要和mapper映射文件的namespace值一致。
2、 mapper接口的方法名称要和mapper映射文件的statement的id一致。
3、 mapper接口的方法参数类型要和mapper映射文件的statement的parameterType的值一致,而且它的参数是一个。
4、 mapper接口的方法返回值类型要和mapper映射文件的statement的resultType的值一致。
1. Mapper.xml(映射文件) (内容类同User.xml)——配置文件与mapper命名一致且在同一目录下
<?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接口代理实现编写规则:
1.映射文件中namespace要等于接口的全路径
2.映射文件中sql语句的id要等于接口的方法名
3.映射文件中传入参数类型要等于接口方法的入参
4.映射文件返回值类型要等于接方法的返回值类型
-->
<mapper namespace="cn.mapper.UserMapper">
<!-- 不再赘述配置文件,详见User.xml -->
<select id="findById" parameterType="java.lang.Integer" resultType="cn.pojo.User">
select * from user where id = #{id}
</select>
<select id="findByName" parameterType="java.lang.String" resultType="cn.pojo.User">
select * from user where username like '%${value}%';
</select>
<insert id="insertUser" parameterType="cn.pojo.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address})
</insert>
</mapper>
//注意编写规则
2.mapper.java接口文件
package cn.mapper;
import java.util.List;
import cn.pojo.User;
public interface UserMapper {
User findById(Integer id);
//返回值是list集合时,mybatis会自动调用selectList()方法
List<User> findByName(String username);
void insertUser(User user);
}
//注意接口文件的编写规则(见配置文件注释)
看到not found的异常时应该想到:没把配置文件引入进核心配置文件!
<!-- 引入映射文件 -->
<mappers>
<mapper resource="User.xml"/>
<!-- 使用class映入接口的全路径
class的使用规则:
1.接口名称和映射名称除拓展名外需要一致
2.映射文件和接口在同一目录下
-->
<mapper class="cn.mapper.UserMapper"/>
</mappers>
测试类:
package mybatis01;
import java.io.InputStream;
import java.util.Date;
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 cn.mapper.UserMapper;
import cn.pojo.User;
public class UserMapperTest {
private SqlSessionFactory factory;
//在测试方法前会执行此初始化方法,构造工厂
@Before
public void setUp() throws Exception{
//通过流将核心配置文件进行读取(注意resources的所在包)
String resource = "SqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//通过核心配置文件输入流来创建工厂
factory = new SqlSessionFactoryBuilder().build(in);
}
@Test
public void testFindById() throws Exception{
SqlSession session = factory.openSession();
//通过getMapper()方法实例化实现类
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.findById(1);
System.out.println(user.toString());
}
@Test
public void testFindByName() throws Exception{
SqlSession session = factory.openSession();
//通过getMapper()方法实例化实现类
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list = mapper.findByName("王");
System.out.println(list);
}
@Test
public void insert() throws Exception{
SqlSession session = factory.openSession();
//通过getMapper()方法实例化实现类
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("宋江");
user.setSex("2");
user.setBirthday(new Date());
user.setAddress("北京");
mapper.insertUser(user);
session.commit();
}
}
//一定得注意提交!增加修改删除等是先改到缓存区的,所以必须提交!
五、SqlMapConfig.xml文件说明
【更新】:详细配置讲解请参见:http://ju.outofmemory.cn/entry/94633
mybatis的配置文件主要分为
全局配置文件
配置数据源、事务等全局信息
映射文件
执行statement相关的信息,SQL语句、输入输出映射等
SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名:给POJO类起别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)——使用插件可以方便的进行分页等的操作
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
1 properties(属性)
SqlMapConfig.xml可以引用java属性文件(.properties)中的配置信息如下:
在classpath下定义db.properties文件(回忆key多加一层的原因:同在mybatis这个大容器中,容易发生命名冲突)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
//如果jdbc.url多个参数需要使用&,请使用转义:&
SqlMapConfig.xml引用如下:(使用EL取值)
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
2.支持别名
别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
map Map
3.自定义别名:
在SqlMapConfig.xml中配置:
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="cn.itcast.mybatis.po.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="cn.itcast.mybatis.po"/>
<package name="其它包"/>
</typeAliases>
//建议遵循驼峰式命名规则,批量别名时默认别名是类名(请使用规范首字母小写)
4.mappers(映射器)
1 <mapper resource=" " />
使用相对于类路径的资源
如:<mapper resource="sqlmap/User.xml" />
2. <mapper class=" " />
使用mapper接口类路径
如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
3.<package name=""/> 包扫描的方式
使用的最多最简便,但是注意遵循相关的规则,与上述接口文件编写规则配置文件一致(映射文件与接口同名并且同一目录)
注册指定包下的所有mapper接口
如:<package name="cn.itcast.mybatis.mapper"/>
最后,贴出目录结构(夹带了一点day02的QueryVo等)
//三个source folder,为的是实现maven的目录结构
今日小结:
1. mybatis是一个持久层框架, 作用是跟数据库交互完成增删改查
2.原生Dao实现(需要接口和实现类)
4.动态代理方式(只需要接口)
mapper接口代理实现编写规则:
1) 映射文件中namespace要等于接口的全路径名称
2) 映射文件中sql语句id要等于接口的方法名称
3) 映射文件中传入参数类型要等于接口方法的传入参数类型
4) 映射文件中返回结果集类型要等于接口方法的返回值类型
5. #{}占位符:占位
如果传入的是基本类型,那么#{}中的变量名称可以随意写
如果传入的参数是pojo类型,那么#{}中的变量名称必须是pojo中的属性.属性.属性...
6. ${}拼接符:字符串原样拼接
如果传入的是基本类型,那么${}中的变量名必须是value
如果传入的参数是pojo类型,那么${}中的变量名称必须是pojo中的属性.属性.属性...
注意:使用拼接符有可能造成sql注入,在页面输入的时候可以加入校验,不可输入sql关键字,不可输入空格
7. 映射文件:
1)传入参数类型通过parameterType属性指定
2)返回结果集类型通过resultType属性指定
8. hibernate和mybatis区别:
hibernate:它是一个标准的orm框架,比较重量级,学习成本高.
优点:高度封装,使用起来不用写sql,开发的时候,会减低开发周期.数据库无关性!
缺点:sql语句无法优化
应用场景:oa(办公自动化系统), erp(企业的流程系统)等,还有一些政府项目,
总的来说,在用于量不大,并发量小的时候使用.
mybatis:它不是一个orm框架, 它是对jdbc的轻量级封装, 学习成本低,比较简单
优点:学习成本低, sql语句可以优化, 执行效率高,速度快.【提高了SQL控制权!】
缺点:编码量较大,会拖慢开发周期
应用场景: 互联网项目,比如电商,P2p等
总的来说是用户量较大,并发高的项目.
【补充注意事项】:当出现无法完成绑定异常时,是由于只有.java文件被编译而xml文件未被编译,方法之一可以在pom.xml中加入resource标签:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8083</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>