1. 创建maven工程,并导入需要的依赖
<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.0modelVersion>
<groupId>com.itheimagroupId>
<artifactId>day04_eesy_03annotation_mybatisartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.32version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
dependencies>
project>
2. 创建实体类和接口
3. 在resources目录下创建Mybatis主配置文件SqlMapConfig.xml,以及所需要的日志文件log4j.properties , 数据库连接配置文件jdbcConfig.properties
SqlMapConfig.xml:
<configuration>
<properties resource="jdbcConfig.properties">properties>
<typeAliases>
<package name="com.itheima.domain">package>
typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}">property>
<property name="url" value="${url}">property>
<property name="username" value="${username}">property>
<property name="password" value="${password}">property>
dataSource>
environment>
environments>
<mappers>
<package name="com.itheima.dao">package>
mappers>
configuration>
log4j.properties:
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
jdbcConfig.properties:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/eesy?serverTimezone=UTC&characterEncoding=utf-8&useUnicode=true
username=root
password=root
在IUserDao接口中新建方法 findAll();
使用 @Select 注解
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
List<User> findAll();
测试类:
package com.itheima.test;
import com.itheima.dao.IUserDao;
import com.itheima.domain.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisAnnoTest {
/**
* 测试基于注解的mybatis使用
* @param args
*/
public static void main(String[] args) throws IOException {
// 1.加载配置文件,获取字节输入流
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 2.根据字节输入流获取SqlSessionFatory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 3.使用SqlSessionFactory产生一个SqlSession
SqlSession sqlSession = factory.openSession();
// 4.使用SqlSession获取IUserDao接口代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
// 5.执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
// 6.释放资源
sqlSession.close();
in.close();
}
}
运行结果:
注意:当使用注解的情况下还存在映射配置文件,就会报错
即使在Mabatis核心配置文件SqlMapConfig.xml中没有用mapper声明使用它也会报错
使用 @Insert 注解
/**
* 保存用户
* @param user
*/
@Insert("insert into user values(null,#{username},#{birthday},#{sex},#{address})")
void saveUser(User user);
/**
* 测试保存操作
*/
@Test
public void testSaveUser(){
User user = new User("艾雅法拉",new Date(),"女","冰岛");
userDao.saveUser(user);
}
从日志文件中可以看到执行的sql语句等,查看数据库也可以看到保存成功
使用 @Update 注解
/**
* 根据id更新用户
* @param user
*/
@Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}")
void updateUser(User user);
/**
* 测试根据id更新用户
*/
@Test
public void testUpdateUser(){
User user = new User(122,"艾雅法拉",new Date(),"女","冰岛");
userDao.updateUser(user);
}
从日志文件中可以看到执行的sql语句等,查看数据库也可以看到更新成功
使用 @Delete 注解
/**
* 根据id删除用户
* @param id
*/
@Delete("delete from user where id=#{id}")
void deleteUser(Integer id);
/**
* 测试根据id删除用户
*/
@Test
public void testDeleteUser(){
userDao.deleteUser(124);
}
/**
* 根据id查询用户
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
User findById(Integer id);
/**
* 测试根据id查询用户
*/
@Test
public void testFindById(){
User user = userDao.findById(41);
System.out.println(user);
}
/**
* 根据用户名称模糊查询用户
* @param name
* @return
*/
@Select("select * from user where username like #{username}")
List<User> findUserByName(String name);
/**
* 根据用户名称模糊查询用户
*/
@Test
public void testFindUserByName(){
List<User> users = userDao.findUserByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
/**
* 根据用户名称模糊查询用户
* @param name
* @return
*/
//@Select("select * from user where username like #{username}")
@Select("select * from user where username like '%${value}%'")
List<User> findUserByName(String name);
这样写就不用在测试类传参的时候写百分号了
/**
* 根据用户名称模糊查询用户
*/
@Test
public void testFindUserByName(){
List<User> users = userDao.findUserByName("王");
for (User user : users) {
System.out.println(user);
}
}
/**
* 查询用户总数量
* @return
*/
@Select("select count(*) from user")
int findTotalUser();
/**
* 查询用户总数量
*/
@Test
public void testFindTotalUser(){
int total = userDao.findTotalUser();
System.out.println(total);
}
可以再sql语句中起别名,不过太麻烦。
使用 @Results 与 @Result 注解来配置
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
@Results(id = "userMap", value = {
@Result(id=true, property = "userId", column = "id"), // id属性设为true表示这个属性是主键
@Result(property = "userName", column = "username"),
@Result(property = "userBirthday", column = "birthday"),
@Result(property = "userSex", column = "sex"),
@Result(property = "userAddress", column = "address")
})
List<User> findAll();
/**
* 查询所有用户
*/
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
当别的方法也想使用时,只需加一个注解 @ResultMap(“userMap”) ,注解里面的值是 @Results 里的id属性,即唯一标识
/**
* 根据id查询用户
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
@ResultMap("userMap")
User findById(Integer id);
查询每个账户同时查询出每个账户所属的用户
账户表:
账户实体类Account:
package com.itheima.domain;
import java.io.Serializable;
/**
* 账户实体类
*/
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
// 多对一(Mybatis称为一对一)映射:一个账户只能属于一个用户
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
IAccountDao接口:
package com.itheima.dao;
import com.itheima.domain.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface IAccountDao {
/**
* 查询所有账户并且获取每个账户所属的用户信息
* @return
*/
@Select("select * from account")
@Results(id="accountMap",value = {
@Result(id = true, property = "id", column = "id"),
@Result(property = "uid", column = "uid"),
@Result(property = "money", column = "money"),
@Result(property = "user", column = "uid", one = @One(select = "com.itheima.dao.IUserDao.findById", fetchType = FetchType.EAGER))
})
List<Account> findAll();
}
/**
* 查询所有账户并且获取每个账户所属的用户信息
*/
@Test
public void testFindAll(){
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println("---------------每个账户信息---------------");
System.out.println(account);
System.out.println(account.getUser());
}
}
查询所有用户信息并且查询出每个用户所拥有的所有账户信息
首先在实体类User中添加一个一对多映射属性
然后在IAccountDao接口中提供一个根据用户id查询账户信息的方法
/**
* 根据用户id查询账户信息
* @param userId
* @return
*/
@Select("select * from account where uid=#{userId}")
List<Account> findAccountByUid(Integer userId);
接着就可以在IUserDao中写方法了:
/**
* 查询所有用户并查询出该用户所拥有的所有账户信息
* @return
*/
@Select("select * from user")
@Results(id = "userMap", value = {
@Result(id=true, property = "userId", column = "id"), // id属性设为true表示这个属性是主键
@Result(property = "userName", column = "username"),
@Result(property = "userBirthday", column = "birthday"),
@Result(property = "userSex", column = "sex"),
@Result(property = "userAddress", column = "address"),
@Result(property = "accounts", column = "id", many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid", fetchType = FetchType.LAZY))
})
List<User> findAll();
/**
* 查询所有用户并查询出该用户所拥有的所有账户信息
*/
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println("--------------每个用户信息--------------");
System.out.println(user);
System.out.println(user.getAccounts());
}
}
测试方法:
/**
* 测试根据id查询用户
*/
@Test
public void testFindById(){
User user = userDao.findById(41);
System.out.println(user);
sqlSession.close(); //释放一级缓存
SqlSession sqlSession2 = factory.openSession(); //重新打开SqlSession
IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
User user2 = userDao2.findById(41);
System.out.println(user2);
sqlSession2.close();
}
无论是xml配置还是使用注解,一级缓存都是默认存在的且一样的,就不赘述了,在一级缓存下运行测试方法:
使用二级缓存步骤:
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
@CacheNamespace(blocking = true)