这几年来注解开发越来越流行,Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射文件了。
1.常用注解说明
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
2.使用Mybatis注解实现基本CRUD
2.1查询数据库
2.2创建maven工程导入jar包的坐标
<?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.itheima</groupId> <artifactId>day04_eesy_03annotation_mybaitis</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> </dependency> </dependencies> </project>
2.3配置数据库连接信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy_mybatis
jdbc.username=root
jdbc.password=123456
<?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="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="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </dataSource> </environment> </environments> <!-- 指定带有注解的dao接口所在位置 --> <mappers> <mapper class="com.itheima.dao.IUserDao"></mapper> </mappers> </configuration>
2.4编写实体类
package com.itheima.domain; import java.io.Serializable; import java.util.Date; public class User implements Serializable { private Integer id; private String username; private String address; private String sex; private Date birthday; 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 getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", address='" + address + '\'' + ", sex='" + sex + '\'' + ", birthday=" + birthday + '}'; } }
2.5使用注解方式开发持久层接口
package com.itheima.dao; import com.itheima.domain.User; import org.apache.ibatis.annotations.Select; import java.util.List; /** * @Select @Insert @Update @Delete */ public interface IUserDao { /** * 查询所有用户 * @return */ @Select("select * from user") List<User> findAll(); }
2.6编写测试方法
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.InputStream; import java.util.List; public class MybatisAnnoTest { /** * 测试基于注解的mybatis使用 * @param args */ public static void main(String[] args) throws Exception{ //1.获取字节输入流 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.根据字节输入流构建SqlSessionFactory SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3.根据SqlSessionFactory生产一个SqlSession SqlSession session = factory.openSession(); //4.使用SqlSession获取Dao的代理对象 IUserDao userDao = session.getMapper(IUserDao.class); //5.执行Dao的方法 List<User> users = userDao.findAll(); for(User user : users){ System.out.println(user); } //6.释放资源 session.close(); in.close(); } }
2.7CURD
package com.itheima.dao; import com.itheima.domain.User; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import java.util.List; /** * @Select @Insert @Update @Delete */ public interface IUserDao { /** * 查询所有用户 * * @return */ @Select("select * from user") List<User> findAll(); /** * 保存用户 * * @param user */ @Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})") void saveUser(User user); @Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}") void updateUser(User user); @Delete("delete from user where id=#{id} ") void deleteUser(Integer userId); @Select("select * from user where id=#{id} ") User findById(Integer userId); @Select("select * from user where username like #{username} ") List<User> findUserByName(String username); @Select("select count(*) from user ") int findTotalUser(); }
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 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 AnnotationCRUDTest { private InputStream in; private SqlSessionFactory factory; private SqlSession session; private IUserDao userDao; @Before public void init() throws Exception { in = Resources.getResourceAsStream("SqlMapConfig.xml"); factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); userDao = session.getMapper(IUserDao.class); } @After public void destroy() throws Exception { session.commit(); session.close(); in.close(); } @Test public void testSave() { User user = new User(); user.setUsername("mybatis annotation"); user.setAddress("nanchang"); userDao.saveUser(user); } @Test public void testUpdate() { User user = new User(); user.setId(60); user.setUsername("mybatis annotation"); user.setAddress("nanchang"); user.setSex("男"); userDao.updateUser(user); } @Test public void testDelete() { userDao.deleteUser(60); } @Test public void testFindOne() { User user = userDao.findById(58); System.out.println(user); } @Test public void testFindByName() { List<User> users = userDao.findUserByName("%mybatis%"); for (User user : users) { System.out.println(user); } } @Test public void testFindTotal(){ int total = userDao.findTotalUser(); System.out.println(total); } }
3.在注解配置中解决数据库字段名和实体类字段名不对应问题
package com.itheima.domain; import java.io.Serializable; import java.util.Date; import java.util.List; public class User implements Serializable { private Integer userId; private String userName; private String userAddress; private String userSex; private Date userBirthday; public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } public String getUserSex() { return userSex; } public void setUserSex(String userSex) { this.userSex = userSex; } public Date getUserBirthday() { return userBirthday; } public void setUserBirthday(Date userBirthday) { this.userBirthday = userBirthday; } @Override public String toString() { return "User{" + "userId=" + userId + ", userName='" + userName + '\'' + ", userAddress='" + userAddress + '\'' + ", userSex='" + userSex + '\'' + ", userBirthday=" + userBirthday + '}'; } }
package com.itheima.dao; import com.itheima.domain.User; import org.apache.ibatis.annotations.*; import java.util.List; /** * @Select @Insert @Update @Delete */ public interface IUserDao { /** * 查询所有用户 * * @return */ @Select("select * from user") @Results(id="userMap",value= { @Result(id = true, column = "id", property = "userId"), @Result(column = "username", property = "userName"), @Result(column = "address", property = "userAddress"), @Result(column = "sex", property = "userSex"), @Result(column = "birthday", property = "userBirthday") }) List<User> findAll(); /** * 根据id查询用户 * * @param userId * @return */ @Select("select * from user where id=#{id} ") // @ResultMap(value = {"userMap"}) @ResultMap("userMap") User findById(Integer userId); /** * 根据用户名称模糊查询 * * @param username * @return */ @Select("select * from user where username like #{username} ") List<User> findUserByName(String username); }
4.多表1对1查询
4.1实体类
package com.itheima.domain; import java.io.Serializable; import java.util.Date; import java.util.List; public class User implements Serializable { private Integer userId; private String userName; private String userAddress; private String userSex; private Date userBirthday; public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } public String getUserSex() { return userSex; } public void setUserSex(String userSex) { this.userSex = userSex; } public Date getUserBirthday() { return userBirthday; } public void setUserBirthday(Date userBirthday) { this.userBirthday = userBirthday; } @Override public String toString() { return "User{" + "userId=" + userId + ", userName='" + userName + '\'' + ", userAddress='" + userAddress + '\'' + ", userSex='" + userSex + '\'' + ", userBirthday=" + userBirthday + '}'; } }
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 + '}'; } }
4.2添加账户的持久层接口并使用注解配置
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,column = "id",property = "id"), @Result(column = "uid",property = "uid"), @Result(column = "money",property = "money"), @Result(property = "user",column = "uid",one=@One(select="com.itheima.dao.IUserDao.findById",fetchType= FetchType.EAGER)) }) List<Account> findAll(); /** * 根据用户id查询账户信息 * @param userId * @return */ @Select("select * from account where uid = #{userId}") List<Account> findAccountByUid(Integer userId); }
package com.itheima.dao; import com.itheima.domain.User; import org.apache.ibatis.annotations.*; import java.util.List; /** * @Select @Insert @Update @Delete */ public interface IUserDao { /** * 查询所有用户 * * @return */ @Select("select * from user") @Results(id="userMap",value= { @Result(id = true, column = "id", property = "userId"), @Result(column = "username", property = "userName"), @Result(column = "address", property = "userAddress"), @Result(column = "sex", property = "userSex"), @Result(column = "birthday", property = "userBirthday") }) List<User> findAll(); /** * 根据id查询用户 * * @param userId * @return */ @Select("select * from user where id=#{id} ") // @ResultMap(value = {"userMap"}) @ResultMap("userMap") User findById(Integer userId); /** * 根据用户名称模糊查询 * * @param username * @return */ @Select("select * from user where username like #{username} ") List<User> findUserByName(String username); }
4.3测试类
package com.itheima.test; import com.itheima.dao.IAccountDao; import com.itheima.domain.Account; 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.InputStream; import java.util.List; public class AccountTest { private InputStream in; private SqlSessionFactory factory; private SqlSession session; private IAccountDao accountDao; @Before public void init()throws Exception{ in = Resources.getResourceAsStream("SqlMapConfig.xml"); factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); accountDao = session.getMapper(IAccountDao.class); } @After public void destroy()throws Exception{ session.commit(); session.close(); in.close(); } @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()); } } }
5.使用注解实现一对多复杂关系映射
需求:
查询用户信息时,也要查询他的账户列表。使用注解方式实现。
分析:
一个用户具有多个账户信息,所以形成了用户(User)与账户(Account)之间的一对多关系。
5.1User实体类加入List<Account>
package com.itheima.domain; import java.io.Serializable; import java.util.Date; import java.util.List; public class User implements Serializable { private Integer userId; private String userName; private String userAddress; private String userSex; private Date userBirthday; //一对多关系映射:一个用户对应多个账户 private List<Account> accounts; public List<Account> getAccounts() { return accounts; } public void setAccounts(List<Account> accounts) { this.accounts = accounts; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } public String getUserSex() { return userSex; } public void setUserSex(String userSex) { this.userSex = userSex; } public Date getUserBirthday() { return userBirthday; } public void setUserBirthday(Date userBirthday) { this.userBirthday = userBirthday; } @Override public String toString() { return "User{" + "userId=" + userId + ", userName='" + userName + '\'' + ", userAddress='" + userAddress + '\'' + ", userSex='" + userSex + '\'' + ", userBirthday=" + userBirthday + '}'; } }
5.2编写用户的持久层接口并使用注解配置
package com.itheima.dao; import com.itheima.domain.User; import org.apache.ibatis.annotations.*; import org.apache.ibatis.mapping.FetchType; import java.util.List; /** * @Select @Insert @Update @Delete */ public interface IUserDao { /** * 查询所有用户 * * @return */ @Select("select * from user") @Results(id="userMap",value= { @Result(id = true, column = "id", property = "userId"), @Result(column = "username", property = "userName"), @Result(column = "address", property = "userAddress"), @Result(column = "sex", property = "userSex"), @Result(column = "birthday", property = "userBirthday"), @Result(property = "accounts",column = "id", many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid", fetchType = FetchType.LAZY)) }) List<User> findAll(); /** * 根据id查询用户 * * @param userId * @return */ @Select("select * from user where id=#{id} ") // @ResultMap(value = {"userMap"}) @ResultMap("userMap") User findById(Integer userId); /** * 根据用户名称模糊查询 * * @param username * @return */ @Select("select * from user where username like #{username} ") List<User> findUserByName(String username); }
5.3编写账户的持久层接口并使用注解配置
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 { /** * 根据用户id查询账户信息 * @param userId * @return */ @Select("select * from account where uid = #{userId}") List<Account> findAccountByUid(Integer userId); }
5.4测试类
@Test public void findAll() { List<User> users = userDao.findAll(); for (User u :users ) { System.out.println("每个用户的信息。。。"); System.out.println(u); System.out.println(u.getAccounts()); } }
6.mybatis基于注解的二级缓存
6.1在SqlMapConfig
<!-- 配置二级缓存 --> <settings> <!-- 开启二级缓存的支持 --> <setting name="cacheEnabled" value="true"/> </settings>
6.2在持久层接口中使用注解配置二级缓存
@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存 public interface IUserDao {}