我是在idea中创建的项目
首先项目大致目录:其中UserMapperImpl和UserTest是多余的,当做纪念所以没有删除。
User pojo类:
package com.ljh.pojo;
public class User {
private Integer id;
private String userName;
private String sex;
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}
UserMapper mapper层:
package com.ljh.Mapper;
import com.ljh.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
//根据id查找
public User selectById(int id);
//查询全部
public List<User> selectAll();
//添加用户
public boolean addUser(User user);
//根据id删除用户
public boolean deleteUser(int id);
//更新用户信息
public boolean updateUser(User user);
//查询当前总人数
public Integer selectCount();
//根据表明查询用户
public List<User> selectByTable(@Param("table")String table);
//login
public List<User> login(@Param("userName")String userName,@Param("sex")String sex);
//需求:查询性别W为男的用户 如果输入姓名就按照姓名查询
public List<User> selectBySex(@Param("username") String userName);
//需求:查询性别为男的用户 如果输入姓名就按照姓名查 如果输入年龄就按照年龄查
public List<User> selectByNameAndAge(@Param("username")String username,@Param("age")Integer age);
//需求:输入姓名就按照姓名查 输入性别就按照性别查
public List<User> selectByNameAndSex(@Param("username")String username,@Param("sex")String sex);
//需求:输入姓名就修改姓名 输入年龄就修改年龄
public void updateNameAndAge(@Param("username")String username,@Param("age")Integer age,@Param("id")Integer id);
//传入多个id查询用户信息
public List<User> selectListUserById(@Param("ids")int[] ids);
//测试trim 方法
public List<User> selectTrim(@Param("username")String username,@Param("sex")String sex);
//测试trim 更新方法
public void updateTrim(@Param("username")String username,@Param("sex")String sex,@Param("id")Integer id);
//测试一级缓存
public User selectCache(int id);
//测试二级缓存
public User selectCache2(int id);
}
UserMapperTest 测试类:
package com.ljh.text;
import com.ljh.Mapper.UserMapper;
import com.ljh.MapperImpl.UserMapperImpl;
import com.ljh.pojo.User;
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 java.io.InputStream;
import java.util.List;
import static org.junit.Assert.*;
public class UserMapperTest {
private SqlSession sqlSession;
private UserMapper userMapper;
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
//mybatis的动态代理 从此不需要再写接口的实现类了
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void selectById() {
System.out.println(userMapper.selectById(1));
}
@Test
public void selectAll() {
System.out.println(userMapper.selectAll());
}
@Test
public void addUser() {
User user = new User();
user.setUserName("小明");
user.setSex("男");
boolean f = this.userMapper.addUser(user);
sqlSession.commit();
if(f){
System.out.println("添加成功");
System.out.println(user.getId());
}
}
@Test
public void deleteUser() {
boolean f = userMapper.deleteUser(6);
sqlSession.commit();
if(f){
System.out.println("删除成功");
}
}
@Test
public void updateUser() {
User user = new User();
user.setUserName("qq");
user.setSex("企鹅");
user.setId(3);
boolean f = userMapper.updateUser(user);
sqlSession.commit();
if(f){
System.out.println("更新成功");
}
}
@Test
public void selectCount(){
Integer integer = userMapper.selectCount();
System.out.println(integer);
}
@Test
public void selectByTable(){
List<User> list = userMapper.selectByTable("user");
for(User u : list){
System.out.println(u);
}
}
@Test
public void login(){
List<User> list = userMapper.login("小明","男");
for(User u : list){
System.out.println(u);
}
}
@Test
public void selectBySex(){
List<User> user = userMapper.selectBySex(null);
for(User u : user){
System.out.println(u);
}
}
@Test
public void selectByNameAndAge(){
List<User> user = userMapper.selectByNameAndAge("",12);
for(User u : user){
System.out.println(u);
}
}
@Test
public void selectByNameAndSex(){
List<User> user = userMapper.selectByNameAndSex("","");
for(User u : user){
System.out.println(u);
}
}
@Test
public void updateNameAndAge(){
userMapper.updateNameAndAge("",30,7);
sqlSession.commit();
}
@Test
public void selectListUserById(){
List<User> user = userMapper.selectListUserById(new int[] {1,2,3});
for(User u : user){
System.out.println(u);
}
}
@Test
public void selectTrim(){
List<User> user = userMapper.selectTrim("aa","bb");
for(User u : user){
System.out.println(u);
}
}
@Test
public void updateTrim(){
userMapper.updateTrim("小李","男",8);
sqlSession.commit();
}
//一级缓存的范围是session 可以关闭session 但是一级缓存默认是无法关闭的 一直开启
// 当mybatis执行查询时 首先回去缓存区命中 如果命中了 就会直接返回结果 如果没有命中 那么才会发生SQL执行查询
@Test
public void selectCache(){
//第一次去查询 会发生sql语句 并执行
User user1 = userMapper.selectCache(1);
System.out.println(user1);
//此方法可以强制清空缓存 并且在执行更新 删除 添加操作后 也会自动清空缓存
sqlSession.clearCache();
//第二次查询的SQL语句和参数一模一样 就不会再发生sql执行了 而是在缓存区命中 直接返回参数
User user2 = userMapper.selectCache(1);
System.out.println(user2);
}
//测试二级缓存 二级缓存的范围是mapper的namespace 是跨session的
//开启二级缓存需要在mapper.xml文件中配置 添加<cache/>即可
@Test
public void selectCache2(){
//第一次查询
User user1 = userMapper.selectCache(1);
System.out.println(user1);
//先关闭session 然后再开启一个新的session 然后执行相同的SQL 如果没有重新发送sql语句的话 那就是从二级缓存中获取的数据
sqlSession.close();
//开启新的session
SqlSession sqlSession = sqlSessionFactory.openSession();
userMapper = sqlSession.getMapper(UserMapper.class);
//第二次查询
User user2 = userMapper.selectCache(1);
System.out.println(user2);
}
}
jdbc.properties :
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///mybatis
username=root
password=root
log4j.properties:
这个配置文件主要是配合pom.xml:中的日志依赖一起使用的
log4j.rootLogger=DEBUG,A1
log4j.logger.org.mybatis=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ljh.mybatis</groupId>
<artifactId>mybatis-01</artifactId>
<version>1.0-SNAPSHOT</version>
<!--<name>mybatis-01</name>
<!– FIXME change it to the project's website –>
<url>http://www.example.com</url>-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!--添加日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
</project>
mybatis-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>
<!--引入外部的jdbc文件-->
<properties resource="jdbc.properties"></properties>
<!--开启驼峰匹配-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--配置别名-->
<typeAliases>
<!-- <typeAlias type="com.ljh.pojo.User" alias="User"></typeAlias>-->
<!--直接扫描包 别名就是类名 不区分大小写 但内容必须一致 比如类名是User 那么别名可以是User 也可以是user-->
<package name="com.ljh.pojo"></package>
</typeAliases>
<!--配置数据源-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driverClass}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--引入mapper文件 执行sql语句-->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
UserMapper.xml:
所有标签的id我是都和接口中的方法名对应一致的 ,所以在此没有具体标明是哪个具体操作
<?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.ljh.Mapper.UserMapper">
<!--开启二级缓存-->
<cache/>
<!--根据id查询用户-->
<select id="selectById" resultType="User">
select * from user where id = #{id}
</select>
<!--type 是查询的结果类型 也可以写实体类的路径 但前提都是需要在mybatis-config文件中开启别名配置-->
<!--resultMap标签中的autoMapping="true" 意思等同于驼峰匹配
将数据库名称 和 实体类中的属性 一一对应
数据库的主键的标签是<id></id> 除此以外其余对应全部用<result></result>标签对应
id和result标签中的column属性表示的是数据库中的名称 property属性表示实体类中的属性
如果数据库中的名称和实体类中的属性名称一致的话 就不需要匹配了
-->
<resultMap id="userResultMap" type="User" >
</resultMap>
<!--定义当前文件中SQL片段 也就是抽取SQL片段
使用sql标签进行定义SQL片段 然后在SQL语句中使用<include refid="sql"/>引入SQL片段
但是目前只能在当前的mapper文件中使用 另外有可以定义一个全局的sql片段 步骤:
在同一目录下创建一个mapper.xml文件 然后将这个文件的命名空间自定义名称 再编写sql标签 定义SQL片段
然后在mybatis-config文件中引入这个文件 最后在SQLmapper文件中通过
<include refid="命名空间.sql标签id"/> 来引入sql片段
-->
<sql id="sql">
select * from
</sql>
<!--查询全部用户-->
<select id="selectAll" resultMap="userResultMap">
<include refid="sql"/>user;
</select>
<!--添加用户-->
<insert id="addUser" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into user(user_name,sex) values(#{userName},#{sex});
</insert>
<!--根据id删除用户-->
<delete id="deleteUser">
delete from user where id = #{id};
</delete>
<!--更新用户-->
<update id="updateUser">
update user set user_name = #{userName},sex = #{sex} where id = #{id};
</update>
<!--查找当前人数-->
<select id="selectCount" resultType="Integer">
select count(1) from user;
</select>
<!--根据表名查询全部用户-->
<select id="selectByTable" resultType="User">
select * from ${table};
</select>
<!-- 当传入多个参数时 有以下三种方式可以传入 第一种和第二种前提是
接口方法中的参数必须使用@Param()声明 第三种可以使用也可以不使用
第一种不需要考虑传入参数类型 可以防止SQL注入
第二种需要考虑参数传入类型 不能防止SQL注入
第三种了解即可 不经常使用 里面的数字1,2是参数的顺序位置
select * from user where user_name = #{username} and sex = #{sex};
select * from user where user_name = '${userName}' and sex = '${sex}';
select * from user where user_name = #{param1} and sex = #{param2};
-->
<!--模拟登陆-->
<select id="login" resultType="User">
select * from user where user_name = '${userName}' and sex = '${sex}';
</select>
<!--需求:如果输入姓名就按照姓名查询 如果不输入 就查找性别为男的用户-->
<select id="selectBySex" resultType="User">
select * from user where sex = '男'
<if test="username != null and username != '' ">
and user_name = #{username};
</if>
</select>
<!--需求:查询性别为男的用户 如果输入姓名就按照姓名查 如果输入年龄就按照年龄查-->
<!--如果第一个when成立的话 后面的都不执行 如果when都没有成立 再执行otherwise-->
<select id="selectByNameAndAge" resultType="User">
select * from user where sex = '男'
<choose>
<when test="username != null and username != '' ">
and user_name = #{username}
</when>
<when test="age != null and age != '' ">
and age = #{age}
</when>
<otherwise></otherwise>
</choose>
</select>
<!--需求:输入姓名就按照姓名查 输入性别就按照性别查-->
<!--如果if条件条件成立 那么where标签就会在SQL语句中自动生成where关键字
如果两个if条件都成立或者一个成立 都会自动去除掉多余的 and关键字 -->
<select id="selectByNameAndSex" resultType="User">
select * from user
<where>
<if test="username != null and username != '' ">
and user_name = #{username}
</if>
<if test="sex != null and sex != '' ">
and sex = #{sex}
</if>
</where>
</select>
<!--需求:输入姓名就修改姓名 输入年龄就修改年龄-->
<!--set标签可以去除多余的,号-->
<update id="updateNameAndAge">
update user
<set>
<if test="username != null and username != '' ">
user_name = #{username},
</if>
<if test="age != null and age != '' ">
age = #{age},
</if>
</set>
where id = #{id};
</update>
<!--传入多个id查询用户-->
<!--foreach就相当于循环 collection是传来的参数名称
item是传入参数的属性名称 需要在下面使用#{属性名称获取 } open是开始 close是结束
separator是分割多个参数的符号 这个标签读取的最终结果就相当于 (1,2,3)-->
<select id="selectListUserById" resultType="User">
select * from user where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
<!--selectTrim 需求:输入姓名就按照姓名查询 输入性别按照性别查询-->
<!--prefix表示前缀 如果下面的if条件成立 那么就会加上前缀也就是查询时加上where关键字
prefixOverrides表示前缀重写 如果两个条件都成立的话 那么会自动去除and 也就是会自动去除前缀重写的内容
同样 前缀重写只能去除语句前面的内容 后面的不行 也不能换为后缀重写-->
<select id="selectTrim" resultType="User">
select * from user
<trim prefix="where" prefixOverrides="and">
<if test="username != null and username !='' ">
and user_name = #{username}
</if>
<if test="sex != null and sex != '' ">
and sex = #{sex}
</if>
</trim>
</select>
<!--测试trim-->
<!--suffix表示后缀 条件成立的话 会加上后缀内容 也就是where id = #{id}
suffixOverrides表示后缀重写 可以去除后面的,号 只能去掉后面 例如上面条件语句前面的and不行
在这里也不能使用前缀重写 只能使用后缀重写去除-->
<update id="updateTrim" >
update user
<trim prefix="set" suffix="where id = #{id}" suffixOverrides=",">
<if test="username != null and username != '' ">
user_name = #{username},
</if>
<if test="sex != null and sex != '' ">
sex = #{sex},
</if>
</trim>
</update>
<!--测试一级缓存-->
<select id="selectCache" resultType="User">
select * from user where id = #{id};
</select>
<!--测试二级缓存-->
<select id="selectCache2" resultType="User">
select * from user where id = #{id};
</select>
</mapper>