目录
注解开发
环境搭建
1.创建Maven工程
2.创建实体类
3.提供接口,并提供增删改查的方法
4.编写SqlMapConfig.xml 主配置文件
5.采用注解的方式,来进行增删改查
6.测试
7.测试保存用户的方法
8.测试更新用户
9.测试删除一个用户
10.根据id查询一个用户
11.根据姓名模糊查询
12.查询所有用户的个数
当实体类的属性名和表中的字段名不一致时,采用注解怎么配置
1.修改实体类的属性名
2.配置实体类的属性和表中字段的映射关系
使用注解进行多表查询
一对一的关系查询:比如查询该账户所对应的用户信息
1.提供账户的实体类
2.提供账户的接口
3.给账户接口上的方法,添加注解,先查询出所有账户
4.测试
5.上面还只是一个单表查询的测试,下来我们要进行多表查询,查询一个账户所对应的用户信息
6.在账户的接口中添加注解,来进行一对一的查询
7.测试
一对多的查询
1.我在User的接口中进行一对多的配置
2.在账户的接口中提供一个方法,以便查询该用户对应的账户时,使用
3.测试
一级缓存的演示
注解开发
@Insert:实现新增 @Update:实现更新 @Delete:实现删除 @Select:实现查询 @Result:实现结果集封装 @Results:可以与@Result 一起使用,封装多个结果集 @ResultMap:实现引用@Results 定义的封装 @One:实现一对一结果集封装 @Many:实现一对多结果集封装 @SelectProvider: 实现动态 SQL 映射
环境搭建
1.创建Maven工程
1.在pom.xml中 引入以下jar包 <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.17</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
2.创建实体类
public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;//get set 方法略 自己补上}
3.提供接口,并提供增删改查的方法
public interface IUserDao {//查询所有的方法List<User> findAll();//保存用户的方法void saveUser(User user);//更新用户void updateUser(User user);//删除一个用户void deleteUser(Integer id);//根据id查询出一个用户User selectUserById(Integer id);//根据姓名模糊查询List<User> selectUserByName(String name);//查询所有用户的个数int selectAllUser(); }
4.编写SqlMapConfig.xml 主配置文件
<configuration> <!--properties 用来加载外部的jdbc的配置文件 --><properties resource="jdbcConfig.properties"/><typeAliases> <!--给该包下所有的类,都起别名,别名可以是类名的小写,大写--><package name="org.westos.domain"/></typeAliases> <environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"></transactionManager><!--配置数据源(连接池)--><dataSource type="POOLED"> <!-- 需要用${jdbc配置文件中的键名}--><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><!--扫描该包下所有的接口,所对应的映射文件--><package name="org.westos.dao"/></mappers> </configuration>
5.采用注解的方式,来进行增删改查
1.在接口的查询所有方法上添加 @select 注解 public interface IUserDao {//查询所有的方法@Select(value = "select * from user")List<User> findAll();}
6.测试
@Testpublic void testFindAll() throws IOException {InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession = factory.openSession();IUserDao dao = sqlSession.getMapper(IUserDao.class);List<User> list = dao.findAll();for (User user : list) {System.out.println(user);}}
7.测试保存用户的方法
1.在接口中的保存用户方法上面,添加 @insert 注解public interface IUserDao {//保存用户的方法@Insert(value = "insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")void saveUser(User user); } 2. 测试 @Testpublic void test() throws IOException {InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession = factory.openSession();IUserDao dao = sqlSession.getMapper(IUserDao.class);User user = new User();user.setUsername("金城武");user.setSex("男");user.setBirthday(new Date());user.setAddress("陕西西安");dao.saveUser(user);//提交事务sqlSession.commit(); in.close();sqlSession.close();
8.测试更新用户
1.在接口中的更新用户方法上添加 @Update 的注解 public interface IUserDao {//更新用户@Update("update user set username=#{username},address=#{address} where id=#{id}")void updateUser(User user); } @Testpublic void test() throws IOException {InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession = factory.openSession();IUserDao dao = sqlSession.getMapper(IUserDao.class);User user = new User();user.setId(66);user.setUsername("金巧巧");user.setAddress("陕西咸阳");dao.updateUser(user); //提交事务sqlSession.commit(); in.close();sqlSession.close(); }
9.测试删除一个用户
1.在接口中的方法上 添加@Delete注解 //删除一个用户@Delete("delete from user where id=#{id}")void deleteUser(Integer id);2.测试:IUserDao dao = sqlSession.getMapper(IUserDao.class);dao.deleteUser(66);//提交事务sqlSession.commit();
10.根据id查询一个用户
1.在接口中的方法上,添加注解 //根据id查询出一个用户@Select(value = "select * from user where id=#{uid}")User selectUserById(Integer id);2.测试IUserDao dao = sqlSession.getMapper(IUserDao.class);User user = dao.selectUserById(66);System.out.println(user);//提交事务sqlSession.commit();
11.根据姓名模糊查询
1.在接口的方法上添加注解//根据姓名模糊查询@Select(value = "select * from user where username like #{name}")List<User> selectUserByName(String name);2.测试IUserDao dao = sqlSession.getMapper(IUserDao.class);List<User> list = dao.selectUserByName("%沈%");for (User user : list) {System.out.println(user);}
12.查询所有用户的个数
1.在接口的方法上添加注解//查询所有用户的个数@Select(value = "select count(*) from user")int selectAllUser();2.测试IUserDao dao = sqlSession.getMapper(IUserDao.class);int i = dao.selectAllUser();System.out.println(i);
当实体类的属性名和表中的字段名不一致时,采用注解怎么配置
1.修改实体类的属性名
public class User implements Serializable {private Integer myid;private String myusername;private Date mybirthday;private String mysex;private String myaddress;//get set 方法略 自己补上} 说明:当我们实体类的属性名和表中字段名不一致后,我们查询用户时,就封装不到实体类当中了那么我们就得进行配置
2.配置实体类的属性和表中字段的映射关系
1.我们就在接口中的查询所有方法上使用 @Results 注解 来配置 实体类属性名和表中字段名的映射关系,配好之后,我们查询所有用户,就可以封装进实体类中了 public interface IUserDao {//查询所有的方法@Select(value = "select * from user")@Results(id = "userMap", value = {//配置主键字段 id = true 表示这是主键字段@Result(id = true, property = "myid", column = "id"),//配置其他普通字段@Result(property = "myusername", column = "username"),@Result(property = "mybirthday", column = "birthday"),@Result(property = "mysex", column = "sex"),@Result(property = "myaddress", column = "address")})List<User> findAll();} 2. 我们接口中还有一个根据id查询单个用户,也要将查询出的用户封装到实体类中,所以这个方法,也要配置 映射关系,但是,我们不是把上面配置好的映射关系,再复制一份,而是通过上面配置的 id名 引用一下即可,那么就使用 @ResultMap 来引用配置好的映射关系//根据id查询出一个用户@Select(value = "select * from user where id=#{uid}")@ResultMap(value = "userMap") //引用上面配置好的映射关系User selectUserById(Integer id);
使用注解进行多表查询
一对一的关系查询:比如查询该账户所对应的用户信息
1.提供账户的实体类
public class Account implements Serializable {private Integer id;private Integer uid;private Double money;//get set 方法略 自己补上}
2.提供账户的接口
public interface IAccountDao {//查询所有账户,以及该账户所对应的用户信息List<Account> findAll(); }
3.给账户接口上的方法,添加注解,先查询出所有账户
public interface IAccountDao {//查询所有账户,以及该账户所对应的用户信息@Select("select * from account")List<Account> findAll(); }
4.测试
public class TestAccount {public static void main(String[] args) throws IOException {InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession = factory.openSession();IAccountDao dao = sqlSession.getMapper(IAccountDao.class);List<Account> list = dao.findAll();for (Account account : list) {System.out.println(account);}in.close();sqlSession.close();} }
5.上面还只是一个单表查询的测试,下来我们要进行多表查询,查询一个账户所对应的用户信息
1.用户表和账户表之间,他是一对多的关系,但是我们站在账户表角度看,那么一个账户就是属于一个用户,也就是说,多对一的关系,在MyBatis中看来就是一对一的关系 2.首先,在账户的实体类中,维护一个用户的对象,来描述这个一对一的关系 public class Account implements Serializable {private Integer id;private Integer uid;private Double money;//在多方维护一个一方的对象,来体现一对一的关系private User user;// get set 方法略 自己补上 }
6.在账户的接口中添加注解,来进行一对一的查询
1.我们先配置账户实体类和账户表的映射关系 2.再配置账户和用户的 一对一的关系 public interface IAccountDao {//查询所有账户,以及该账户所对应的用户信息@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 = "org.westos.dao.IUserDao.selectUserById", fetchType = FetchType.EAGER))})List<Account> findAll(); } 说明://配置一对一的关系 那么在@Result注解中有一个one属性可以配置一对一/** property = "user" 多方维护的一方的对象* column = "uid" 多方表中通过uid这个字段跟一方产生关系* one 一对一关系的配置select = "org.westos.dao.IUserDao.selectUserById" 查询依据 使用的是用户接口中通过id查询单个用户的这个方法fetchType = FetchType.EAGER 加载模式,使用的立即加载一般一对一的查询使用立即加载一对多 使用延迟加载* */
7.测试
public class TestAccount {public static void main(String[] args) throws IOException {InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession = factory.openSession();IAccountDao dao = sqlSession.getMapper(IAccountDao.class);List<Account> list = dao.findAll();for (Account account : list) {System.out.println(account);//获取该账户对应得用户信息User user = account.getUser();System.out.println(user);}in.close();sqlSession.close();} }
一对多的查询
我们站在用户的角度,那么一个用户肯定有多个账户 我们在用户的实体类中维护一个集合来描述这个一对多的关系 public class User implements Serializable {private Integer myid;private String myusername;private Date mybirthday;private String mysex;private String myaddress;//提供一个集合来描述一对多的关系private List<Account> accounts;//get set 方法略 自己 补上 }
1.我在User的接口中进行一对多的配置
public interface IUserDao {//查询所有的方法@Select(value = "select * from user")@Results(id = "userMap", value = {//配置主键字段 id = true 表示这是主键字段@Result(id = true, property = "myid", column = "id"),//配置其他普通字段@Result(property = "myusername", column = "username"),@Result(property = "mybirthday", column = "birthday"),@Result(property = "mysex", column = "sex"),@Result(property = "myaddress", column = "address"),//配置一对多的关系@Result(property = "accounts",column = "id",many = @Many(select = "org.westos.dao.IAccountDao.findAccountById",fetchType = FetchType.LAZY ))})List<User> findAll(); //根据id查询出一个用户@Select(value = "select * from user where id=#{uid}")@ResultMap(value = "userMap")User selectUserById(Integer id);} 说明: //配置一对多的关系// property = "accounts", 一方维护的集合名// column = "id" 一方 id 这个字段跟多方产生关系@Result(property = "accounts",column = "id",many = @Many(//查询依据,使用账户接口中的方法根据uid查询该用户对应的账户select = "org.westos.dao.IAccountDao.findAccountById",fetchType = FetchType.LAZY //延迟加载 ))
2.在账户的接口中提供一个方法,以便查询该用户对应的账户时,使用
public interface IAccountDao {//查询所有账户,以及该账户所对应的用户信息@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 = "org.westos.dao.IUserDao.selectUserById", fetchType = FetchType.EAGER))})List<Account> findAll(); //提供一个根据uid查询账户的方法//注意是根据uid查询@Select("select * from account where uid=#{uid}")Account findAccountById(Integer id); }
3.测试
@Testpublic void test() throws IOException {InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession = factory.openSession();IUserDao dao = sqlSession.getMapper(IUserDao.class);List<User> list = dao.findAll();for (User user : list) {System.out.println(user);//获取改用户所对应的账户信息List<Account> accounts = user.getAccounts();System.out.println(accounts);} in.close();sqlSession.close(); }
一级缓存的演示
1、什么是缓存存在于内存中的临时数据。为什么使用缓存减少和数据库的交互次数,提高执行效率。什么样的数据能使用缓存,什么样的数据不能使用适用于缓存:经常查询并且不经常改变的。 省市区数据的正确与否对最终结果影响不大的。小软文,自媒体写的花边新闻不适用于缓存:经常改变的数据数据的正确与否对最终结果影响很大的。例如:商品的库存,银行的汇率,股市的牌价。
Mybatis中的一级缓存一级缓存:它指的是Mybatis中SqlSession对象的缓存。当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时,mybatis的一级缓存也就消失了。 一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
public interface IUserDao2 {//更新用户@Update("update user set username=#{username},address=#{address} where id=#{id}")void updateUser(User user);//根据id查询出一个用户@Select("select * from user where id=#{uid}")User selectUserById(Integer id); }
public class TestUserDao {public static void main(String[] args) throws IOException {//加载主配置文件InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");//构建SessionFactorySqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);//获取sqlSessionSqlSession sqlSession = sessionFactory.openSession();//获取接口的代理对象IUserDao dao = sqlSession.getMapper(IUserDao.class); //第一次查询,根据id查询出一个用户User user = dao.selectUserById(59);System.out.println(user); //不要重写toString方法,打印一下地址值 //sqlSession.clearCache();清空一级缓存//第一次查询出用户后,我们更新用户,也会清空一级缓存//user.setUsername("张全蛋");//user.setAddress("陕西咸阳");//dao.updateUser(user);//再进行第二次查询,如果之前没有清空缓存,就会从缓存中查询,如果清空了,就从数据库中查询User user2 = dao.selectUserById(59);System.out.println(user2); //System.out.println(user2==user); //对比两次查询的对象是否是同一个对象sqlSession.commit(); //释放资源in.close();sqlSession.close();} }