Mybatis框架复习总结
基本操作
框架搭建步骤:
- 导入jar包
- 拷贝配置文件,根据所需修改
- 根据对应数据库表写pojo类
- 定义mapper接口中的方法
- 实现mapper.xml(sql映射文件)文件中的sql语句
- 在SqlMapConfig文件中注册mapper文件
- 测试增删改查
导入jar包
拷贝配置文件,根据所需修改
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=qa.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
log4j.rootLogger=debug,file,stdout
<?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="db.properties"></properties>
<!--设置日志打印输出-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 数据库环境配置-->
<environments default="development">
<environment id="development">
<!-- 事务处理的方式-->
<!-- 除了JDBC,还有managed容器来管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源: jndi(Java命名目录接口),pooled(数据连接池),unpooled(不使用连接池) -->
<!-- 使用mybatis框架必须使用数据库连接池-->
<dataSource type="POOLED">
<!-- 数据库的配置-->
<!-- 配置数据库驱动,url,用户名,密码-->
<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>
<!-- 注册mapper文件-->
<mappers>
<mapper class=""></mapper>
</mappers>
</configuration>
根据对应数据库表写pojo类
定义mapper接口中的方法
要注意的点:
- mapper接口中的方法名,就是mapper.xml文件中statement语句的id,所以不要命名不要太随意。
- 普通的增删改,返回值都是int
实现mapper.xml文件中的sql语句
mapper.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必须与mapper接口的类路径相同-->
<mapper namespace="com.oracle.mapper.UserMapper">
<select id="getById" parameterType="int" resultType="com.oracle.pojo.User">
select * from users where id = #{哈哈哈哈哈}
</select>
<select id="getAllUsers" resultType="com.oracle.pojo.User">
select * from users
</select>
<insert id="save" parameterType="com.oracle.pojo.User">
insert into users(username, birthday, sex, address) values (#{username},#{birthday},#{sex},#{address})
</insert>
<update id="update" parameterType="com.oracle.pojo.User">
update users set username = #{username},birthday = #{birthday},sex = #{sex},address = #{address} where id = #{id}
</update>
<delete id="delete" parameterType="int">
delete from users where id = #{反正这写啥都行,我就不好好写}
</delete>
<insert id="insertCarryId" parameterType="com.oracle.pojo.User">
insert into users(id,username, birthday, sex, address) values (#{id},#{username},#{birthday},#{sex},#{address})
</insert>
<!-- #{}有一个要求,如果你的入参(parameterType)是8种基本数据类型,那么你的#{}中写啥都行,写你的名字都行!
如果你的入参是对象类型,那么#{}中写的就是该对象的成员变量,大小写区分-->
</mapper>
需要注意:
- mapper的namespace必须与mapper接口的类路径相同
- 每个statement的id都要与接口中所对应的方法名相同
- sql标签可以将重复的SQL语句封装起来,下次使用时通过include标签的refid属性引用其id号即可
<sql id="allCloums">
id,username,birthday,sex,address
</sql>
<select id="getAllUsers" resultType="com.oracle.pojo.User">
select <include refid="allCloums"></include> from users
</select>
所以有了sql标签后我们就不要用星号*了,因为星号在查询的时候他会到数据库中找寻对应表的全部列名,相当耗费时间,所以我们强烈不推荐使用星号代表所有列名。
测试增删改查
使用junit单元测试可使用@Before注解,使得每一个单元测试执行的前导条件@Before注解的方法先去执行,使用输入流和工厂构建方式实例化SqlSession对象和使用反射机制实例化实体类对应的mapper接口。
SqlSession sqlSession;
UserMapper userMapper;
@Before
public void setSession() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = factory.openSession();
userMapper = sqlSession.getMapper(UserMapper.class);
}
小优化:
小优化:给pojo类起别名
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<typeAlias type="com.oracle.pojo.User" alias="user"></typeAlias>
</typeAliases>
<!-- 数据库环境配置-->
<environments default="development">
注意typeAliases标签的书写顺序,它一定是写在settings标签之后,environments标签之前,实在不行查看dtd文件看它们的顺序。
小优化:使用包的方式注册mapper文件
当mapper文件太多,而且它们都在一个包下,我只需要注册一个存放mapper文件的包就行:
<mappers>
<!-- <mapper class="com.oracle.mapper.UserMapper"></mapper>-->
<package name="com.oracle.mapper"/>
</mappers>
#{}和${}的区别
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,**#{}**可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个基本类型值,#{}括号中可以是value或其它任何名称。
{}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, {}括号中只能是value。
parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
插入后返回主键id
<insert id="insertUserReturnId" parameterType="User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select
LAST_INSERT_ID()
</selectKey>
insert into users (username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
其中selectKey表示查询主键,keyProperty表示该主键在实体类中对应的成员变量名,order="AFTER"指在插入后执行查询主键语句,因为mysql的自增原理,只有插入后我才知道主键是啥。
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
Mysql使用uuid()函数实现主键
<insert id="insertCarryUUID" parameterType="User">
<selectKey resultType="java.lang.String" order="BEFORE"
keyProperty="id">
select uuid()
</selectKey>
insert into users(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
前提是你的数据库表的主键长度够用,而且POJO类中主键类型必须是UUID类型的,否则插入会会出现java.lang.IllegalArgumentException: argument type mismatch
异常。
总结:Mapper接口开发需要遵循以下规范:
1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。
2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
5、 接口与xml文件必同名,而且在同一个路径下
mybatis支持别名
别名 | 映射的类型 |
---|---|
_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 |
boolen | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
hashmap | HashMap |
关于resultMap
一般来讲,resultMap有两种作用:
- 解决数据库表和实体类属性名不一致的问题
<resultMap id="OrderMap" type="order">
<id property="id" column="id"></id>
<result property="userId" column="user_id"></result>
<result property="number" column="number"></result>
<result property="createTime" column="cratetime"></result>
<result property="note" column="note"></result>
</resultMap>
<select id="getById" parameterType="int" resultMap="OrderMap">
select * from orders where id = #{id}
</select>
resultMap的type类型要写实体类的别名或全类名。
id用id标签绑定,其他属性使用result绑定。
property指当前实体类属性名,column指当前数据库表字段名。
除了id和property属性,还可以指定jdbctype,网上查询资料,对jdbcType这个参数的描述不多,作用不清楚,大概的意思是“jdbcType这个参数的应用场景就是,当执行mapping文件的时候,有个映射的参数为空,那么无法确定他的类型,这个时候就需要jdbcType来确定类型“。
resultMap中jdbcType中属性,javaType与jdbcType的对应关系
Java Type | JDBC Type |
---|---|
String | CHAR |
String | VARCHAR |
String | LONGVARCHAR |
java.math.BigDecimal | NUMERIC |
java.math.BigDecimal | DECIMAL |
boolean | BIT |
boolean | BOOLEAN |
byte | TINYINT |
short | SMALLINT |
int | INTEGER |
long | BIGINT |
float | REAL |
double | FLOAT |
double | DOUBLE |
byte[] | BINARY |
byte[] | VARBINARY |
byte[] | LONGVARBINARY |
java.sql.Date | DATE |
java.sql.Time | TIME |
java.sql.Timestamp | TIMESTAMP |
Clob | CLOB |
Blob | BLOB |
Array | ARRAY |
mapping of underlying type | DISTINCT |
Struct | STRUCT |
Ref | REF |
java.net.URL[color=red][/color] | DATALINK |
- 解决主外键关联问题