动态代理存在的意义
在三层架构中,业务逻辑层要通过接口访问数据访问层的功能,动态代理可以实现。
动态代理实现规范:
1)UsersMapper.xml文件与UsersMapper.java的接口必须同一个目录下
2)UserMapper.xml文件与UserMapper.java的接口的文件名必须一致,后缀不管
3)UserMapper.xml文件中标签的id值与UserMapper.java的接口中方法的名称完全一致
4)UserMapper.xml文件中标签的paramType的属性值与UserMapper.java的接口中方法的参数类型完全一致
5)UserMapper.xml文件中标签的resultType与UserMapper.java的接口中方法的返回值类型完全一致
6)UserMapper.xml文件中namespace属性必须是接口的完全限定名称
7)在SqlMapperConfig.xml文件中注册mapper文件时,使用class=接口的完全限定名称
核心配置文件
<?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>
<!-- 读取jdbc.properties属性文件-->
<properties resource="jdbc.properties"></properties>
<!-- 设置日志输出-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--注册实体类的别名-->
<typeAliases>
<package name="com.huaze.pojo"/>
</typeAliases>
<!-- 配置环境变量-->
<environments default="develoment">
<environment id="develoment">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 注册mapper.xml-->
<mappers>
<mapper class="com.huaze.mapper.UsersMapper"></mapper>
</mappers>
</configuration>
UsersMapper.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>
<!-- 读取jdbc.properties属性文件-->
<properties resource="jdbc.properties"></properties>
<!-- 设置日志输出-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--注册实体类的别名-->
<typeAliases>
<package name="com.huaze.pojo"/>
</typeAliases>
<!-- 配置环境变量-->
<environments default="develoment">
<environment id="develoment">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 注册mapper.xml-->
<mappers>
<mapper class="com.huaze.mapper.UsersMapper"></mapper>
</mappers>
</configuration>
创建实体类
package com.huaze.pojo;
import java.util.Date;
public class Users {
private Integer id;
private String userName;
private Date birthday;
private String sex;
public String address;
public Users() {
}
public Users(Integer id, String userName, Date birthday, String sex, String address) {
this.id = id;
this.userName = userName;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}
public Users(String userName, Date birthday, String sex, String address) {
this.userName = userName;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Users{" +
"id=" + id +
", userName='" + userName + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
测试
package com.huaze.test;
import com.huaze.mapper.UsersMapper;
import com.huaze.pojo.Users;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyTest {
//提升作用域
SqlSession sqlSession;
@Before //在所有Test方法执行前 先执行的方法
public void openSqlSession() throws IOException {
// 1、读取核心配置文件
InputStream in= Resources.getResourceAsStream("SqlMapperConfig.xml");
// 2、创建工厂对象
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
// 3、取出sqlSession
sqlSession=factory.openSession();
}
@After //在所有Test方法执行后 后执行的方法
public void closeSqlSession(){
sqlSession.close();
}
@Test
public void testGetAll(){
// 取出动态代理的对象 完成接口中方法的调用 实则是调用xml文件中相应的标签的功能
UsersMapper usMapper=sqlSession.getMapper(UsersMapper.class);
System.out.println(usMapper.getClass());
// List<Users>list=sqlSession.selectList("")
}
}
#{}和${}
#{}是对非字符串拼接的参数的占位符,如果入参是简单数据类型,#{}里可以任意写,但如果入参是对象类型,则#{}里必须是对象的成员变量的名称,而且区分大小写。#{}可以有效防止sql注入。底层使用的是PreparedStatement对象,是安全的的数据库访问.
${}主要是针对字符串拼接的替换,如果入参是基本数据类型,${}里必须是value(3.5.1以下版本,以上随便写),但是如果入参是对象类型,则${}里必须是对象的成员变量的名称。${}还可以替换列名和表名,存在sql注入风险,尽量少用(一般用于模糊查询中)
优化后的模糊查询
concat('%',#{name},'%') 防止sql注入
字符串替换
需求:模糊地址或用户名查询
代码实现
接口
// 模糊地址和用户名查询
List<Users> getByNameOrAddress (
@Param("columnName")
String columnName,
@Param("columnValue")
String columnValue
);
UsersMapper.xml
<!-- 如果参数超过一个则 parameterType 不写-->
<select id="getByNameOrAddress" resultType="users">
select id,username,birthday,sex,address
from users
where ${columnName} like concat('%',#{columnValue},'%')
</select>
测试
@Test
public void getByNameOrAddress(){
List<Users>list=usMapper.getByNameOrAddress("username","小");
list.forEach(users -> System.out.println(users));
}
返回主键值
在插入语句结束后,返回自增的主键值到入参的users对象的id属性中
<insert id="insert" parameterType="users">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into users(username,birthday,sex,address)values(#{userName},#{birthday},#{sex},#{address)
</insert>
<selectKey>标签的参数详解
keyProperty:users对象的那个属性来接返回的主键值
resultType:返回的逐渐的类型
order:在插入语句执行前,还是执行后返回主键的值
UUID
这是一个全球唯一字符串,由36个字母数字下划线组成