Mybatis 笔记——动态代理增删改查
Posted Johnny*
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis 笔记——动态代理增删改查相关的知识,希望对你有一定的参考价值。
mapper动态代理方式的CRUD
动态代理方式也称为接口开发。是基于以下原理:
约定优于配置。
硬编码方式
Configuration conf = new Configuration();
conf.setName(“myProject”);
配置方式
abc.xml文件中:
myProject
约定
默认值就是myProject
上述优先级是: 约定 >配置方式>硬编码方式
约定的目的是: 省略statement,即根据约定可以直接定位到SQL语句。
要实现该约定则PersonMapper.java接口中方法必须遵守以下规定:
- 方法名与personMapper.xml文件中的标签id值相同
- 方法参数与parameterType类型一致。如果personMapper.xml的标签中没有parameterType,则说明该方法无需方法参数。
- 方法的返回值与resultType类型一致。(无论查询结果是一个 还是多个(Person、List),在personMapper.xml标签中的resultType中只写 一个(Person),但是方法中的返回值则需要根据返回结果决定是否使用List;如果没有resultType,则说明方法的返回值为void)
除了以上要实现接口中的方法personMapper.xml中的SQL标签一一对应外,还需:
personMapper.xml的namespace的值要为接口的全类名。这样就可以实现一个接口对应一个mapper文件
匹配的过程
- 根据接口全类名==namespace,找到对应的mapper.xml文件
- 根据方法名==id值,唯一定位SQL标签。
PersonMapper.java 接口
package com.johnny.mapper;
import java.util.List;
import com.johnny.entity.Person;
public interface PersonMapper {
List<Person> selectAllPerson();
Person selectPersonById(int id);
void addPerson(Person per);
void deletePersonById(int id);
void updatePerson(Person per);
}
PersonMapper.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="com.johnny.mapper.PersonMapper"> <!-- 该mapper的命名空间要为对应接口的全类名 -->
<select id="selectPersonById" resultType="com.johnny.entity.Person">
select * from person where id = #{id}
</select>
<select id="selectAllPerson" resultType="com.johnny.entity.Person">
select * from person
</select>
<insert id="addPerson" parameterType="com.johnny.entity.Person">
insert into person(id, age, name) values( #{id}, #{age}, #{name})
</insert>
<update id="updatePerson" parameterType ="com.johnny.entity.Person">
update person set name = #{name}, age =#{age} where id = #{id}
</update>
<delete id="deletePersonById" parameterType ="int">
delete from person where id=#{id}
</delete>
</mapper>
config.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">
<!-- 通过environments 的 default 和 enviroment的id 来指定数据库环境 -->
<environment id="development">
<!-- transactionManager 事务提交方式
JDBC : 利用JDBC 方式处理事务 (rollback、commit、close)
MANAGED: 将事务交由其他组件(如spring、jobss)去托管,默认会关闭连接
<property name = "closeConnection" value ="false"/> 来指定不关闭
-->
<transactionManager type="JDBC"/>
<!-- 数据源类型:
UNPOOLED: 传统的JDBC模式(每次访问数据库需要打开、关闭数据操作,比较消耗性能)
POOLED : 使用数据库连接池方式
JNDI: 从tomcat中获取一个内置的数据库连接池
-->
<dataSource type="POOLED">
<!-- 配置数据库信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/goodsadmin"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载映射文件 -->
<mapper resource="com/johnny/mapper/personMapper.xml"/>
</mappers>
</configuration>
TestMybatis.java
package com.johnny.test;
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 com.johnny.entity.Person;
import com.johnny.mapper.PersonMapper;
public class TestMybatis {
public static void selectPersonById() throws IOException {
//1、加载资源文件:获取mybatis配置文件输入流/MybatisDemo0/src/com/johnny/entity/config.xml
InputStream in = Resources.getResourceAsStream("config.xml");
//2、 通过 SqlSessionFactoryBuilder 获得SqlSessionFactory 的实例
SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(in);
//3、获取session对象 --相当于JDBC中的Connection对象
SqlSession session = sqlFactory.openSession();
//xml命名空间+sql语句id
PersonMapper personMapper = session.getMapper(PersonMapper.class);
personMapper.selectPersonById(2);
}
public static void selectAllPerson() throws IOException {
InputStream in = Resources.getResourceAsStream("config.xml");
SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlFactory.openSession();
PersonMapper personMapper = session.getMapper(PersonMapper.class);
List<Person> allPerson = personMapper.selectAllPerson();
for(Person per: allPerson)
System.out.println(per);
}
public static void addPerson() throws IOException {
InputStream in = Resources.getResourceAsStream("config.xml");
SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlFactory.openSession();
PersonMapper personMapper = session.getMapper(PersonMapper.class);
personMapper.addPerson(new Person(4, "sally", 35));
session.commit();
System.out.println("添加成功!");
}
public static void updatePerson() throws IOException {
InputStream in = Resources.getResourceAsStream("config.xml");
SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlFactory.openSession();
PersonMapper personMapper = session.getMapper(PersonMapper.class);
Person per = new Person();
per.setId(4);
per.setName("ls");
per.setAge(28);
personMapper.updatePerson(per);
session.commit();
System.out.println("修改成功!");
}
public static void deletePerson() throws IOException {
InputStream in = Resources.getResourceAsStream("config.xml");
SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlFactory.openSession();
PersonMapper personMapper = session.getMapper(PersonMapper.class);
personMapper.deletePersonById(4);
//提交事务
session.commit();
System.out.println("删除成功!");
}
public static void main(String[] args) throws IOException {
selectAllPerson();
// addPerson();
// updatePerson();
deletePerson();
selectAllPerson();
}
}
Person.java
package com.johnny.entity;
public class Person {
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return this.id+"- "+ this.name+"- " +this.age;
}
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(int id,String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
private int id;
private String name;
private int age;
}
优化
数据库配置信息采用动态引入方式:
可以将配置信息 单独放入 db.properties文件中,然后再动态引入
db.properties文件中:
k=v
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/goodsadmin
username=用户名
password=密码
config.xml文件中:
加载数据库配置信息文件
引入之后,使用${key}
<?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="dp.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 配置数据库信息 -->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载映射文件 -->
<mapper resource="com/johnny/mapper/personMapper.xml"/>
</mappers>
</configuration>
批量设置别名
config.xml文件的configuration标签下
<!-- 设置别名 -->
<typeAliases>
<!-- 设置单个别名 -->
<!-- <typeAlias type="com.johnny.entity.Person" alias="person"/> -->
<!-- 批量设置 别名为类名(不带包名),且忽略大小写-->
<!-- 使用包扫描的方式来定义别名,mybatis会自动扫描指定包下的所有类并将别名装配到上下文中 -->
<package name="com.johnny.entity" />
</typeAliases>
之后resultType和parameterType便可直接使用person而无需全类名限定(即com.johnny.entity.Person)
类型处理器(类型转换器)
Mybatis自带类型转化器
Mybatis内置了一些常见类的别名
自定义Mybatis类型转化器
如果对象的属性类型与表中的字段类型对不上,但是名字对得上。那么mybatis会匹配的上。比如数据字段为sex(int(12) ),Person类属性名也为sex(Boolean)时,即使类型不一致但名字一致,此时mybatis仍可正确匹配上。
要是类型和名字都不匹配则需借助resultMap标签实现一 一映射。
mybatis中似乎有Boolean(java)转Integer(JDBC)的内置转换器
<select id="selectPersonByIdWithConverter" resultMap="personMapping">
select * from person where id = #{id}
</select>
<resultMap type="person" id="personMapping">
<id property="id" column="id"/>
<result property="name" column ="name"/>
<result property="age" column ="age"/>
<result property="sex" column ="perSex" />
</resultMap>
执行结果仍可正确映射:
1- johnny- 22 - 性别:false
2- weiwei- 98 - 性别:true
3- feng- 25 - 性别:true
若使用自定义的类型转化器
首先要声明实现TypeHandler接口的类,实现转换器有2种选择:
i.实现接口TypeHandler接口
ii.继承BaseTypeHandler
package com.johnny.converter;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
public class BooleanAndNumber extends BaseTypeHandler<Boolean>{
/**
* Java 类型- > JDBC类型
* @param ps PreparedStatement对象
* @param i 数据库表字段所在列
* @param parameter Java类型参数
* @param jdbcType 数据库类型
*/
public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType)
throws SQLException {
if(parameter) ps.setInt(i, 1);
else ps.setInt(i, 0);
}
//按列名获取 一般执行该方法
public Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {
System.out.println(1112);
return rs.getInt(columnName)== 1;
}
//按索引获取
public Boolean getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
System.out.println(1113);
return rs.getInt(columnIndex)== 1;
}
public Boolean getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
System.out.println(1114);
return cs.getInt(columnIndex) ==1;
}
}
其次,配置config.xml
<!-- 设置自定义类转换器 -->
<typeHandlers>
<typeHandler handler="com.johnny.converter.BooleanAndNumber" javaType="Boolean" jdbcType="INTEGER"/>
</typeHandlers>
最后在需要转换的位置引用:
<select id="selectPersonByIdWithConverter" resultMap="personMapping">
select * from person where id = #{id}
</select>
<resultMap type="person" id="personMapping">
<id property="id" column="id"/>
<result property="name" column ="name"/>
<result property="age" column ="age"/>
<result property="sex" column ="perSex" typeHandler="com.johnny.converter.BooleanAndNumber"/>
</resultMap>
resultMap可以实现2个功能:
1.类型转换
2.属性-字段的映射关系
<select id="selectPersonByIdWithConverter" resultMap="personMapping">
select * from person where id = #{id}
</select>
<resultMap type="person" id="personMa以上是关于Mybatis 笔记——动态代理增删改查的主要内容,如果未能解决你的问题,请参考以下文章