Mybatis 简介 1.三层架构:
表现层:用于展示数据
业务层:是处理业务需求
持久层:是和数据库交互的
2.持久层次技术解决方案:
JDBC技术:Connection,PreparedStatement,ResultSet
Spring的JdbcTemplate:Spring中对Jdbc的简单封装
Apache的DBUtils:它和Spring的JdbcTemplate相似,也是对Jdbc的简单封装。
以上的都不是框架,JDBC是规范,Spring的JdbcTemplate和Apache的DBUtils都只是工具类。
概述: mybatis是一个持久层框架,用java编写的。它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁琐的过程,它使用了ORM思想实现了结果集的封装。
ORM(Object Relational Mapping)对象关系映射:就是把数据库和实体类的属性对应起来,实体类中的属性和数据库的字段名称保持一致,让我们可以操作实体类就实现操作数据表。
入门 基于XML的方式开发 第一步:创建maven工程
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <?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.xhh460</groupId > <artifactId > mybatis1</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.12</version > <scope > test</scope > </dependency > </dependencies > </project >
第二步:创建实体类和dao的接口
实体类:User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package com.xhh460.entity;import java.io.Serializable;import java.util.Date;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId () { return id; } public String getUsername () { return username; } public Date getBirthday () { return birthday; } public String getSex () { return sex; } public String getAddress () { return address; } public void setId (Integer id) { this .id = id; } public void setUsername (String username) { this .username = username; } public void setBirthday (Date birthday) { this .birthday = birthday; } public void setSex (String sex) { this .sex = sex; } public void setAddress (String address) { this .address = address; } }
dao接口:IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.xhh460.dao;import com.xhh460.entity.User;import java.util.List;public interface IUserDao { List<User> findAll () ; }
第三步:创建Mybatis的主配置文件SqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?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 > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/user_db" /> <property name ="username" value ="root" /> <property name ="password" value ="admin@123" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="com/xhh460/dao/UserDao.xml" /> </mappers > </configuration >
第四步:创建映射配置文件IUserDao.xml
1 2 3 4 5 6 7 8 9 10 <?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.xhh460.dao.IUserDao" > <select id ="findAll" resultType ="com.xhh460.entity.User" > select * from user </select > </mapper >
注意事项 :
创建IUserDao.xml和IUserDao.java时名称是为了和我们之前的知识保持一致。在Mybatis中它把持久层的操作接口名称和映射文件也叫做Mapper,所以IUserDao和IUserMapper是一样的
mybatis的映射文件位置必须和dao接口的包结构相同。
映射配置文件的mapper标签的namespace属性的取值必须是dao接口的全限定类名
映射配置文件的操作配置,id属性的取值必须是dao接口的方法名。
当我们完成2,3,4步操作之后,我们在开发中就无须编写dao的实现类。
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.xhh460.test;import com.xhh460.dao.IUserDao;import com.xhh460.entity.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 MybatisTest { public static void main (String[] args) throws IOException { InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(in); SqlSession session = factory.openSession(); IUserDao userDao = session.getMapper(IUserDao.class ) ; List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } session.close(); in.close(); } }
输出:
注意事项:
不要忘记在映射配置中告知mybatis要封装到哪个实体类中。配置的方式:指定实体类的全限定类名。
基于注解的方式开发 把上述项目中的IUserDao.xml文件移处,在dao接口的方法上使用@Select
注解,并指定SQL语句,同时需要在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名。
IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.xhh460.dao;import com.xhh460.entity.User;import org.apache.ibatis.annotations.Select;import java.util.List;public interface IUserDao { @Select ("select * from user" ) List<User> findAll () ; }
SqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?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 > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/user_db" /> <property name ="username" value ="root" /> <property name ="password" value ="admin@123" /> </dataSource > </environment > </environments > <mappers > <mapper class ="com.xhh460.dao.IUserDao" /> </mappers > </configuration >
传统dao层代码 UserDaoImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.xhh460.dao;import com.xhh460.entity.User;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import java.util.List;public class UserDaoImpl implements IUserDao { private SqlSessionFactory factory; public UserDaoImpl (SqlSessionFactory factory) { this .factory = factory; } @Override public List<User> findAll () { SqlSession session = factory.openSession(); List<User> users = session.selectList("com.xhh460.dao.IUserDao.findAll" ); session.close(); return users; } }
MyBatisTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.xhh460.test;import com.xhh460.dao.IUserDao;import com.xhh460.dao.UserDaoImpl;import com.xhh460.entity.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 MybatisTest { public static void main (String[] args) throws IOException { InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(in); IUserDao userDao = new UserDaoImpl(factory); List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } in.close(); } }
Mybatis设计模式分析
自定义Mybatis分析 查询所有的分析
创建代理对象的分析 mybatis在使用代理dao的方式实现增删改查时做的事情:
创建代理对象
在代理对象中调用selectList
需要自定的类:
class Resource
class SqlSessionFactoryBuilder
interface SqlSessionFactory
interface SqlSession
步骤:
1.SqlSessionFactoryBuilder接收SqlMapConfig.xml文件流,构建出SqlSessionFactory对象
2.SqlSessionFactory读取SqlMapConfig.xml中连接数据库和mapper映射信息。用来生产出真正操作数据库的SqlSession对象
3.SqlSession对象有两大作用:(1)生成接口代理对象 。(2)定义通用增删改查方法 。无论哪个分支,除了连接数据库信息,还需要得到sql语句
(1)生成接口代理对象:在SqlSessionImpl对象的getMapper方法中分两步来实现。第一:先用SqlSessionFactory读取数据库连接信息创建Connection对象。第二:通过jdk代理模式创建出代理对象作为getMapper方法返回值,这里主要工作是在创建对象时第三个参数处理类里面得到sql语句。执行对应CRUD操作。
(2)定义通用的增删改查方法:在SqlSessionImpl对象中提供selectList()方法,[当然实际Mybatis框架中还有selectOne,insert等方法]这些方法内也分两步。第一:用SqlSessionFactory读取数据库连接信息创建出jdbc的Connection对象。第二:直接得到sql语句,使用jdbc的Connection对象进行对应的CRUD操作。
4.封装结果集:无论使用分支1生成代理对象,还是直接使用分支2提供的CRUD方法,我们都要对返回的数据库结果集进行封装,变成java对象返回给调用者。所以我们还必须要知道调用者所需要的返回类型。
详细代码查看:F:\java框架合集\Mybatis\mybatis_design
CRUD操作 目录结构
entity层
User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package com.xhh460.entity;import java.io.Serializable;import java.util.Date;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId () { return id; } public String getUsername () { return username; } public Date getBirthday () { return birthday; } public String getSex () { return sex; } public String getAddress () { return address; } public void setId (Integer id) { this .id = id; } public void setUsername (String username) { this .username = username; } public void setBirthday (Date birthday) { this .birthday = birthday; } public void setSex (String sex) { this .sex = sex; } public void setAddress (String address) { this .address = address; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}' ; } }
QueryVo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.xhh460.entity;public class QueryVo { private User user; public User getUser () { return user; } public void setUser (User user) { this .user = user; } }
dao层文件
IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 package com.xhh460.dao;import com.xhh460.entity.QueryVo;import com.xhh460.entity.User;import java.util.List;public interface IUserDao { List<User> findAll () ; void saveUser (User user) ; void updateUser (User user) ; void deleteUser (Integer userId) ; User findById (Integer userId) ; List<User> findByName (String name) ; int findTotal () ; List<User> findUserByVo (QueryVo vo) ; }
Resouces文件夹
resouces.com.xhh460.dao.IUserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?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.xhh460.dao.IUserDao" > <select id ="findAll" resultType ="com.xhh460.entity.User" > select * from user </select > <insert id ="saveUser" parameterType ="com.xhh460.entity.User" > <selectKey keyProperty ="id" keyColumn ="id" resultType ="int" order ="AFTER" > select last_insert_id(); </selectKey > insert into user (username,address,sex,birthday)values (#{username},#{address},#{sex},#{birthday}); </insert > <update id ="updateUser" parameterType ="com.xhh460.entity.User" > update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id} </update > <delete id ="deleteUser" parameterType ="java.lang.Integer" > delete from user where id = #{uid} </delete > <select id ="findById" parameterType ="java.lang.Integer" resultType ="com.xhh460.entity.User" > select * from user where id = #{uid} </select > <select id ="findByName" parameterType ="java.lang.String" resultType ="com.xhh460.entity.User" > select * from user where username like #{username} </select > <select id ="findTotal" resultType ="java.lang.Integer" > select count(id) from user </select > <select id ="findUserByVo" parameterType ="com.xhh460.entity.QueryVo" resultType ="com.xhh460.entity.User" > select * from user where username like #{user.username} </select > </mapper >
Resources.log4j.properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 log4j.rootCategory =debug, CONSOLE, LOGFILE log4j.logger.org.apache.axis.enterprise =FATAL, CONSOLE 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 log4j.appender.LOGFILE =org.apache.log4j.FileAppender log4j.appender.LOGFILE.File =f:\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
Resources.SqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?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 > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/user_db" /> <property name ="username" value ="root" /> <property name ="password" value ="admin@123" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="com/xhh460/dao/IUserDao.xml" /> </mappers > </configuration >
对应测试文件:
MybatisTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 package com.xhh460.test;import com.xhh460.dao.IUserDao;import com.xhh460.entity.QueryVo;import com.xhh460.entity.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.Date;import java.util.List;public class MybatisTest { private InputStream in; private SqlSession sqlSession; private IUserDao userDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(); userDao = sqlSession.getMapper(IUserDao.class ) ; } @After public void destroy () throws IOException { sqlSession.commit(); sqlSession.close(); in.close(); } @Test public void testFindAll () { List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } } @Test public void testSave () { User user = new User(); user.setUsername("javaer" ); user.setAddress("CUP" ); user.setSex("男" ); user.setBirthday(new Date()); System.out.println("保存操作之前:" +user); userDao.saveUser(user); System.out.println("保存操作之后:" +user); List<User> users = userDao.findAll(); for (User user1 : users){ System.out.println(user1); } } @Test public void testUpdate () { User user = new User(); user.setId(6 ); user.setUsername("javaer" ); user.setAddress("CUP" ); user.setSex("男" ); user.setBirthday(new Date()); userDao.updateUser(user); } @Test public void testDelete () { userDao.deleteUser(8 ); } @Test public void testFindOne () { User user = userDao.findById(6 ); if (user != null ){ System.out.println(user); }else { System.out.println("此用户不存在" ); } } @Test public void testFindByName () { List<User> users = userDao.findByName("%小%" ); for (User user : users){ System.out.println(user); } } @Test public void testFindTotal () { int total = userDao.findTotal(); System.out.println(total); } @Test public void testFindByVo () { QueryVo vo = new QueryVo(); User user = new User(); user.setUsername("%小%" ); vo.setUser(user); List<User> u = userDao.findUserByVo(vo); for (User user1: u){ System.out.println(user1); } } }
传递pojo对象 Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
ognl表达式(Object Graphic Navigation Language):对象图导航语言,它是通过对象中的取值方法来获取数据。在写法上把get给省略了。比如我们获取用户的名称:类中的写法:user.getUsername()
。OGNL表达式写法:user.username
。
mybatis中为什么能直接写username,而不用user.呢?
是因为子啊parameterType中已经提供了属性所属的类,所以此时不需要写对象名。
传递pojo包装对象 开发中通过传递pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Mybatis的输出结果封装 解决实体类属性和数据库列名不对应的两种方式方式
此处resultMap对应以上的userMap
查询方法源码追踪
增删改方法源码追踪
无论是增加删除还是修改,最终都会走到PreparedStatement对象的execute()方法。
PreparedStatement对象中:
execute():它能执行CRUD中的任意一种语句,它的返回值是一个boolean类型,表示的是是否有结果集,有结果集是true,没有则是false。
executeUpdate():它能执行CUD语句,查询无法执行,返回值是影响数据库记录的行数。
executeQuery():它只能执行Select语句,无法执行增删改,返回值是:执行结果封装的结果集ResultSet对象。
代理Dao方法源码追踪
到此处我们对MapperProxy进行追踪,即代理类
所以有了代理,我们就不用写dao实现类了。
SqlMapConfig.xml配置文件 propeties
:属性
settings
:全局配置参数
typeAliases
:类型别名
typeHandlers
:类型处理器
objectFactory
:对象工厂
plugins
:插件
environments
:环境集合属性对象
envieronment
:环境子属性对象
transactionManager
:事务管理
dataSource
:数据源
mappers
:映射器
SqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <?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" /> <typeAliases > <package name ="com.xhh460.entity" /> </typeAliases > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <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 ="com.xhh460.dao" /> </mappers > </configuration >
连接池 我们在实际的开发中都会使用到连接池,因为它可以减少我们获取连接所消耗的时间。
mybaits中的连接池:
mybatis连接池提供了三种方式的配置:
配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池的方式。
type属性的取值:
POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对此规范的实现。
UNPOOLED:采用传统的获取连接的方式,虽然也实现了java.sql.DataSource接口,但是并没有使用池的思想。
JNDI:采用服务器提供的JNDI技术实现来获取DataSource对象,不同的服务器所能拿到的DataSource是不一样的。注意:如果不 是web或maven的war工程,是不能使用的。
POOLED属性 :从池中获取一个连接来用
实现了DataSource接口
POOLED过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 private PooledConnection popConnection (String username, String password) throws SQLException { boolean countedWait = false ; PooledConnection conn = null ; long t = System.currentTimeMillis(); int localBadConnectionCount = 0 ; while (conn == null ) { synchronized (state) { if (!state.idleConnections.isEmpty()) { conn = state.idleConnections.remove(0 ); if (log.isDebugEnabled()) { log.debug("Checked out connection " + conn.getRealHashCode() + " from pool." ); } } else { if (state.activeConnections.size() < poolMaximumActiveConnections) { conn = new PooledConnection(dataSource.getConnection(), this ); if (log.isDebugEnabled()) { log.debug("Created connection " + conn.getRealHashCode() + "." ); } } else { PooledConnection oldestActiveConnection = state.activeConnections.get(0 ); long longestCheckoutTime = oldestActiveConnection.getCheckoutTime(); if (longestCheckoutTime > poolMaximumCheckoutTime) { state.claimedOverdueConnectionCount++; state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime; state.accumulatedCheckoutTime += longestCheckoutTime; state.activeConnections.remove(oldestActiveConnection); if (!oldestActiveConnection.getRealConnection().getAutoCommit()) { try { oldestActiveConnection.getRealConnection().rollback(); } catch (SQLException e) { log.debug("Bad connection. Could not roll back" ); } } conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this ); conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp()); conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp()); oldestActiveConnection.invalidate(); if (log.isDebugEnabled()) { log.debug("Claimed overdue connection " + conn.getRealHashCode() + "." ); } } else { try { if (!countedWait) { state.hadToWaitCount++; countedWait = true ; } if (log.isDebugEnabled()) { log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection." ); } long wt = System.currentTimeMillis(); state.wait(poolTimeToWait); state.accumulatedWaitTime += System.currentTimeMillis() - wt; } catch (InterruptedException e) { break ; } } } } if (conn != null ) { if (conn.isValid()) { if (!conn.getRealConnection().getAutoCommit()) { conn.getRealConnection().rollback(); } conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password)); conn.setCheckoutTimestamp(System.currentTimeMillis()); conn.setLastUsedTimestamp(System.currentTimeMillis()); state.activeConnections.add(conn); state.requestCount++; state.accumulatedRequestTime += System.currentTimeMillis() - t; } else { if (log.isDebugEnabled()) { log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection." ); } state.badConnectionCount++; localBadConnectionCount++; conn = null ; if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) { if (log.isDebugEnabled()) { log.debug("PooledDataSource: Could not get a good connection to the database." ); } throw new SQLException("PooledDataSource: Could not get a good connection to the database." ); } } } } } if (conn == null ) { if (log.isDebugEnabled()) { log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection." ); } throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection." ); } return conn; }
UNPOOLED :每次创建一个新的连接来用
mybatis中的事务 mybatis通过sqlsession对象的commit方法和rollback方法实现事务的提交和回滚。
mybaits中基于XML配置的动态SQL语句的使用 Mybatis中的映射文件中,前面我们的SQL都是比较简单的,有时候在业务逻辑复杂的时候,我们的SQL是动态变化的,此时在前面的学习中我们的SQL就不能满足我们的要求了。
动态SQL:
mappers配置文件中的几个标签:<if><where><foreach><sql>
java.com.xhh460.dao.IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.xhh460.dao;import com.xhh460.entity.QueryVo;import com.xhh460.entity.User;import java.util.List;public interface IUserDao { List<User> findAll () ; User findById (Integer userId) ; List<User> findByName (String name) ; List<User> findUserByVo (QueryVo vo) ; List<User> findUserByCondition (User user) ; List<User> findUserInIds (QueryVo vo) ; }
resources.com.xhh460.dao.IUserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 <?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.xhh460.dao.IUserDao" > <resultMap id ="userMap" type ="com.xhh460.entity.User" /> <sql id ="defaultUser" > select * from user </sql > <select id ="findAll" resultMap ="userMap" > <include refid ="defaultUser" /> </select > <select id ="findById" parameterType ="java.lang.Integer" resultMap ="userMap" > select * from user where id = #{uid} </select > <select id ="findByName" parameterType ="java.lang.String" resultMap ="userMap" > select * from user where username like #{username} </select > <select id ="findUserByVo" parameterType ="com.xhh460.entity.QueryVo" resultMap ="userMap" > select * from user where username like #{user.username} </select > <select id ="findUserByCondition" resultMap ="userMap" parameterType ="com.xhh460.entity.User" > select * from user <where > <if test ="username != null" > and username = #{username} </if > <if test ="sex != null" > and sex = #{sex} </if > </where > </select > <select id ="findUserInIds" resultMap ="userMap" parameterType ="com.xhh460.entity.QueryVo" > select * from user <where > <if test ="ids != null and ids.size()>0" > <foreach collection ="ids" open ="and id in (" close =")" item ="uid" separator ="," > #{uid} </foreach > </if > </where > </select > </mapper >
test.java.com.xhh460.test.MybatisTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 package com.xhh460.test;import com.xhh460.dao.IUserDao;import com.xhh460.entity.QueryVo;import com.xhh460.entity.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.ArrayList;import java.util.Date;import java.util.List;public class MybatisTest { private InputStream in; private SqlSession sqlSession; private IUserDao userDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(true ); userDao = sqlSession.getMapper(IUserDao.class ) ; } @After public void destroy () throws IOException { sqlSession.close(); in.close(); } @Test public void testFindAll () { List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } } @Test public void testFindOne () { User user = userDao.findById(6 ); if (user != null ){ System.out.println(user); }else { System.out.println("此用户不存在" ); } } @Test public void testFindByName () { List<User> users = userDao.findByName("%小%" ); for (User user : users){ System.out.println(user); } } @Test public void testFindByVo () { QueryVo vo = new QueryVo(); User user = new User(); user.setUsername("%小%" ); vo.setUser(user); List<User> u = userDao.findUserByVo(vo); for (User user1: u){ System.out.println(user1); } } @Test public void testFindByCondition () { User u = new User(); u.setUsername("javaer" ); u.setSex("男" ); List<User> users = userDao.findUserByCondition(u); for (User user :users){ System.out.println(user); } } @Test public void testFindInIds () { QueryVo vo = new QueryVo(); List<Integer> list = new ArrayList<Integer>(); list.add(1 ); list.add(3 ); list.add(6 ); vo.setIds(list); List<User> users = userDao.findUserInIds(vo); for (User user : users){ System.out.println(user); } } }
mybatis中的多表操作
特例:如果拿出每一个订单,他都只属于一个用户,所以Mybatis就把多对一看成了一对一。
mybatis中的多表查询:
示例:用户和账户
一个用户可以有多个账户
一个账户只能属于一个用户(多个账户也可以属于同一个用户)
步骤:
1.建立两张表:用户表和账户表
让账户表和用户表之间具备一对多的关系:需要使用外键在账户表中添加
2.建立两个实体类:用户实体类和账户实体类
让用户和账户的实体类能体现出来一对多的关系
3.建立两个配置文件:用户的配置文件和账户的配置文件
4.实现配置:
当我们查询用户时,可以同时得到用户下所包含的账户信息
当我们查询账户时,可以同时得到账户的所属用户信息
建立数据表account
1 2 3 4 5 6 7 8 9 10 DROP TABLE IF EXISTS `account` ;CREATE TABLE `account` ( `ID` int (11 ) NOT NULL COMMENT '编号' , `UID` int (11 ) default NULL COMMENT '用户编号' , `MONEY` double default NULL COMMENT '金额' , PRIMARY KEY (`ID` ), KEY `FK_Reference_8` (`UID` ), CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID` ) REFERENCES `user` (`id` ) ) ENGINE =InnoDB DEFAULT CHARSET =utf8;
然后向account表中插入数据:
一对一查询 然后我们进行account的一对一查询操作:
执行结果:
目录:
com.xhh460.dao.IAccountDao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.xhh460.dao;import com.xhh460.entity.Account;import com.xhh460.entity.AccountUser;import java.util.List;public interface IAccountDao { List<Account> findAll () ; List<AccountUser> findAllAccount () ; }
com.xhh460.entity.Account.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package com.xhh460.entity;import java.io.Serializable;public class Account implements Serializable { private Integer id; private Integer uid; private Double money; private 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; } public User getUser () { return user; } public void setUser (User user) { this .user = user; } @Override public String toString () { return "Account{" + "id=" + id + ", uid=" + uid + ", money=" + money + '}' ; } }
com.xhh460.entity.User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package com.xhh460.entity;import java.io.Serializable;import java.util.Date;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId () { return id; } public String getUsername () { return username; } public Date getBirthday () { return birthday; } public String getSex () { return sex; } public String getAddress () { return address; } public void setId (Integer id) { this .id = id; } public void setUsername (String username) { this .username = username; } public void setBirthday (Date birthday) { this .birthday = birthday; } public void setSex (String sex) { this .sex = sex; } public void setAddress (String address) { this .address = address; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}' ; } }
com.xhh460.entity.AccountUser.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package com.xhh460.entity;public class AccountUser extends Account { private String username; private String address; 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; } @Override public String toString () { return super .toString()+" AccountUser{" + "username='" + username + '\'' + ", address='" + address + '\'' + '}' ; } }
resources.com.xhh460.dao.IAccountDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?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.xhh460.dao.IAccountDao" > <resultMap id ="accountUserMap" type ="com.xhh460.entity.Account" > <id property ="id" column ="aid" /> <result property ="uid" column ="uid" /> <result property ="money" column ="money" /> <association property ="user" column ="uid" javaType ="com.xhh460.entity.User" > <id property ="id" column ="id" /> <result property ="username" column ="username" /> <result property ="address" column ="address" /> <result property ="sex" column ="sex" /> <result property ="birthday" column ="birthday" /> </association > </resultMap > <select id ="findAll" resultMap ="accountUserMap" > select u.*,a.id as aid,a.uid,a.money from account a,user u where u.id = a.uid </select > <select id ="findAllAccount" resultType ="com.xhh460.entity.AccountUser" > select a.*,u.username,u.address from account a ,user u where u.id = a.uid </select > </mapper >
测试文件AccountTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 package com.xhh460.test;import com.xhh460.dao.IAccountDao;import com.xhh460.dao.IUserDao;import com.xhh460.entity.Account;import com.xhh460.entity.AccountUser;import com.xhh460.entity.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 AccountTest { private InputStream in; private SqlSession sqlSession; private IAccountDao accountDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(true ); accountDao = sqlSession.getMapper(IAccountDao.class ) ; } @After public void destroy () throws IOException { sqlSession.close(); in.close(); } @Test public void testFindAll () { List<Account> accounts = accountDao.findAll(); for (Account account : accounts){ System.out.println("---------每个account的信息----------" ); System.out.println(account); System.out.println(account.getUser()); } } @Test public void testFindAllAccountUser () { List<AccountUser> accountUsers = accountDao.findAllAccount(); for (AccountUser accountUser : accountUsers){ System.out.println(accountUser); } } }
输出结果:
一对多查询 目录:
java.com.xhh460.dao.IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.xhh460.dao;import com.xhh460.entity.User;import java.util.List;public interface IUserDao { List<User> findAll () ; User findById (Integer userId) ; }
java.com.xhh460.entity.Account.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package com.xhh460.entity;import java.io.Serializable;public class Account implements Serializable { private Integer id; private Integer uid; private Double money; private 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; } public User getUser () { return user; } public void setUser (User user) { this .user = user; } @Override public String toString () { return "Account{" + "id=" + id + ", uid=" + uid + ", money=" + money + '}' ; } }
java.com.xhh460.entity.User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 package com.xhh460.entity;import java.io.Serializable;import java.util.Date;import java.util.List;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; private List<Account> accounts; public List<Account> getAccounts () { return accounts; } public void setAccounts (List<Account> accounts) { this .accounts = accounts; } public Integer getId () { return id; } public String getUsername () { return username; } public Date getBirthday () { return birthday; } public String getSex () { return sex; } public String getAddress () { return address; } public void setId (Integer id) { this .id = id; } public void setUsername (String username) { this .username = username; } public void setBirthday (Date birthday) { this .birthday = birthday; } public void setSex (String sex) { this .sex = sex; } public void setAddress (String address) { this .address = address; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + ", accounts=" + accounts + '}' ; } }
resources.com.xhh460.dao.IUserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?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.xhh460.dao.IUserDao" > <resultMap id ="userAccountMap" type ="com.xhh460.entity.User" > <id property ="id" column ="id" /> <result property ="username" column ="username" /> <result property ="address" column ="address" /> <result property ="sex" column ="sex" /> <result property ="birthday" column ="birthday" /> <collection property ="accounts" ofType ="com.xhh460.entity.Account" > <id column ="aid" property ="id" /> <result column ="uid" property ="uid" /> <result column ="money" property ="money" /> </collection > </resultMap > <select id ="findAll" resultMap ="userAccountMap" > select *,a.id as aid from user u left outer join account a on u.id = a.uid </select > <select id ="findById" parameterType ="java.lang.Integer" resultType ="com.xhh460.entity.User" > select * from user where id = #{uid} </select > </mapper >
测试文件:
com.xhh460.test.UserTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 package com.xhh460.test;import com.xhh460.dao.IUserDao;import com.xhh460.entity.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.ArrayList;import java.util.List;public class UserTest { private InputStream in; private SqlSession sqlSession; private IUserDao userDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(true ); userDao = sqlSession.getMapper(IUserDao.class ) ; } @After public void destroy () throws IOException { sqlSession.close(); in.close(); } @Test public void testFindAll () { List<User> users = userDao.findAll(); for (User user : users){ System.out.println("-----每个用户的信息-----" ); System.out.println(user); } } }
输出信息:
1 2 3 4 5 6 7 8 9 10 11 12 -----每个用户的信息----- User{id=1 , username='小灰灰' , birthday=Thu Dec 10 00 :00 :00 CST 2020 , sex='男' , address='大理' , accounts=[Account{id=1 , uid=1 , money=1000.0 }]} -----每个用户的信息----- User{id=3 , username='老王' , birthday=Mon Dec 14 00 :00 :00 CST 2020 , sex='男' , address='大理' , accounts=[Account{id=2 , uid=3 , money=1000.0 }]} -----每个用户的信息----- User{id=6 , username='javaer' , birthday=Sun Jan 24 20 :23 :55 CST 2021 , sex='男' , address='CUP' , accounts=[Account{id=3 , uid=6 , money=2000.0 }, Account{id=4 , uid=6 , money=3000.0 }]} -----每个用户的信息----- User{id=2 , username='岳绮罗' , birthday=Thu Feb 06 00 :00 :00 CST 2020 , sex='女' , address='大理' , accounts=[]} -----每个用户的信息----- User{id=4 , username='小红' , birthday=Mon Jan 13 00 :00 :00 CST 2020 , sex='女' , address='大理' , accounts=[]} -----每个用户的信息----- User{id=11 , username='pythoner' , birthday=Mon Jan 25 16 :46 :01 CST 2021 , sex='女' , address='CUP' , accounts=[]}
多对多查询 一个用户可以有很多个角色
一个角色可以赋予多个用户
1.建立两张表:用户表,角色表。
让用户表和角色表具有多对多的关系,需要使用中间表,中间表中包含各自的主键,在中间表中是外键
role
表
中间表:user_role
表
user
表
2.建立两个实体:用户实体类和角色实体类
让用户和角色的实体类能体现出来多对多的关系。
java.com.xhh460.entity.User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 package com.xhh460.entity;import java.io.Serializable;import java.util.Date;import java.util.List;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; private List<Role> roles; public List<Role> getRoles () { return roles; } public void setRoles (List<Role> roles) { this .roles = roles; } public Integer getId () { return id; } public String getUsername () { return username; } public Date getBirthday () { return birthday; } public String getSex () { return sex; } public String getAddress () { return address; } public void setId (Integer id) { this .id = id; } public void setUsername (String username) { this .username = username; } public void setBirthday (Date birthday) { this .birthday = birthday; } public void setSex (String sex) { this .sex = sex; } public void setAddress (String address) { this .address = address; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + ", roles=" + roles + '}' ; } }
main.java.com.xhh460.entity.Role.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package com.xhh460.entity;import java.io.Serializable;import java.util.List;public class Role implements Serializable { private Integer roleId; private String roleName; private String roleDesc; private List<User> users; public List<User> getUsers () { return users; } public void setUsers (List<User> users) { this .users = users; } public Integer getRoleId () { return roleId; } public void setRoleId (Integer roleId) { this .roleId = roleId; } public String getRoleName () { return roleName; } public void setRoleName (String roleName) { this .roleName = roleName; } public String getRoleDesc () { return roleDesc; } public void setRoleDesc (String roleDesc) { this .roleDesc = roleDesc; } @Override public String toString () { return "Role{" + "roleId=" + roleId + ", roleName='" + roleName + '\'' + ", roleDesc='" + roleDesc + '\'' + ", users=" + users + '}' ; } }
3.创建dao层文件
java.com.xhh460.dao.IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.xhh460.dao;import com.xhh460.entity.User;import java.util.List;public interface IUserDao { List<User> findAll () ; }
java.com.xhh460.entity.IRoleDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.xhh460.dao;import com.xhh460.entity.Role;import java.util.List;public interface IRoleDao { List<Role> findAll () ; }
4.建立两个配置文件:用户的配置文件和角色的配置文件
resources.com.xhh460.dao.IRoleDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?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.xhh460.dao.IRoleDao" > <resultMap id ="roleMap" type ="com.xhh460.entity.Role" > <id property ="roleId" column ="rid" /> <result property ="roleName" column ="role_name" /> <result property ="roleDesc" column ="role_desc" /> <collection property ="users" ofType ="com.xhh460.entity.User" > <id column ="id" property ="id" /> <id column ="username" property ="username" /> <id column ="address" property ="address" /> <id column ="sex" property ="sex" /> <id column ="birthday" property ="birthday" /> </collection > </resultMap > <select id ="findAll" resultMap ="roleMap" > SELECT u.*,r.id as rid,r.role_name,r.role_desc FROM role r LEFT OUTER JOIN user_role ur ON r.id = ur.RID LEFT OUTER JOIN user u ON u.id = ur.UID </select > </mapper >
resources,com.xhh460.dao.IUserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?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.xhh460.dao.IUserDao" > <resultMap id ="userMap" type ="com.xhh460.entity.User" > <id property ="id" column ="id" /> <result property ="username" column ="username" /> <result property ="address" column ="address" /> <result property ="sex" column ="sex" /> <result property ="birthday" column ="birthday" /> <collection property ="roles" ofType ="com.xhh460.entity.Role" > <id property ="roleId" column ="rid" /> <result property ="roleName" column ="role_name" /> <result property ="roleDesc" column ="role_desc" /> </collection > </resultMap > <select id ="findAll" resultMap ="userMap" > SELECT u.*,r.id as rid,r.role_name,r.role_desc FROM role r LEFT OUTER JOIN user_role ur ON r.id = ur.RID LEFT OUTER JOIN user u ON u.id = ur.UID </select > </mapper >
5.实现配置:
当我们查询角色时,可以同时得到角色的所赋予的用户信息:
1 2 3 SELECT u.*,r.id as rid,r.role_name,r.role_desc FROM role r LEFT OUTER JOIN user_role ur ON r.id = ur.RID LEFT OUTER JOIN user u ON u.id = ur.UID
当我们查询用户时,可以同时得到用户所包含的角色信息
1 2 3 SELECT u.*,r.id as rid,r.role_name,r.role_desc FROM user u LEFT OUTER JOIN user_role ur ON u.id = ur.UID LEFT OUTER JOIN role r on r.id = ur.RID
6.输出结果:
测试文件:
test.java.com.xhh460.test.RoleTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 package com.xhh460.test;import com.xhh460.dao.IRoleDao;import com.xhh460.dao.IUserDao;import com.xhh460.entity.Role;import com.xhh460.entity.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 RoleTest { private InputStream in; private SqlSession sqlSession; private IRoleDao roleDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(true ); roleDao = sqlSession.getMapper(IRoleDao.class ) ; } @After public void destroy () throws IOException { sqlSession.close(); in.close(); } @Test public void testFindAll () { List<Role> roles = roleDao.findAll(); for (Role role : roles){ System.out.println("-----每个角色的信息-----" ); System.out.println(role); } } }
输出结果:
1 2 3 4 5 6 -----每个角色的信息----- Role{roleId=1 , roleName='院长' , roleDesc='管理整个学院' , users=[User{id=1 , username='小灰灰' , birthday=Thu Dec 10 00 :00 :00 CST 2020 , sex='男' , address='大理' , roles=null }, User{id=3 , username='老王' , birthday=Mon Dec 14 00 :00 :00 CST 2020 , sex='男' , address='大理' , roles=null }]} -----每个角色的信息----- Role{roleId=2 , roleName='总裁' , roleDesc='管理整个公司' , users=[User{id=6 , username='javaer' , birthday=Sun Jan 24 20 :23 :55 CST 2021 , sex='男' , address='CUP' , roles=null }]} -----每个角色的信息----- Role{roleId=3 , roleName='校长' , roleDesc='管理整个学校' , users=[]}
test.java.com.xhh460.test.UserTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 package com.xhh460.test; import com.xhh460.dao.IUserDao; import com.xhh460.entity.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.ArrayList; import java.util.List; /** * @Author coderYang * @Date 2021/1/27 16:28 */ public class UserTest { private InputStream in; private SqlSession sqlSession; private IUserDao userDao; @Before //用于在测试方法执行之前执行 public void init() throws IOException { //1.读取配置文件,生成字节输入流 in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.获取SqlSessionFactory对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3.获取SqlSession对象 sqlSession = factory.openSession(true); //4.获取dao的代理对象 userDao = sqlSession.getMapper(IUserDao.class); } @After //用于在测试方法执行之后执行 public void destroy() throws IOException{ //提交事务 // sqlSession.commit(); //释放资源 sqlSession.close(); in.close(); } /** * 测试查询所有 */ @Test public void testFindAll(){ List<User> users = userDao.findAll(); for (User user : users){ System.out.println("-----每个用户的信息-----"); System.out.println(user); } } }
输出结果:
1 2 3 4 5 6 7 8 -----每个用户的信息----- User{id=1 , username='小灰灰' , birthday=Thu Dec 10 00 :00 :00 CST 2020 , sex='男' , address='大理' , roles=[Role{roleId=1 , roleName='院长' , roleDesc='管理整个学院' , users=null }]} -----每个用户的信息----- User{id=3 , username='老王' , birthday=Mon Dec 14 00 :00 :00 CST 2020 , sex='男' , address='大理' , roles=[Role{roleId=1 , roleName='院长' , roleDesc='管理整个学院' , users=null }]} -----每个用户的信息----- User{id=6 , username='javaer' , birthday=Sun Jan 24 20 :23 :55 CST 2021 , sex='男' , address='CUP' , roles=[Role{roleId=2 , roleName='总裁' , roleDesc='管理整个公司' , users=null }]} -----每个用户的信息----- User{id=null , username='null' , birthday=null , sex='null' , address='null' , roles=[Role{roleId=3 , roleName='校长' , roleDesc='管理整个学校' , users=null }]}
JNDI JNDI(Java Naming and Directory Interface ),类似于在一个中心注册一个东西,以后要用的时候,只需要根据名字去注册中心查找,注册中心返回你要的东西。web程序,我们可以将一些东西(比如数据库相关的)交给服务器软件去配置和管理(有全局配置和单个web程序的配置),在程序代码中只要通过名称查找就能得到我们注册的东西,而且如果注册的东西有变,比如更换了数据库,我们只需要修改注册信息,名称不改,因此代码也不需要修改。
如:
项目目录:
项目还是原来的Mybatis项目中对数据库访问的文件,只是现在我们通过JNDI的形式去交给tomcat服务器管理数据。
所需要进行配置的文件:
java.resources.SqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?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" /> <typeAliases > <package name ="com.xhh460.entity" /> </typeAliases > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" /> <dataSource type ="JNDI" > <property name ="data_source" value ="java:comp/env/jdbc/eesy_mybatis" /> </dataSource > </environment > </environments > <mappers > <package name ="com.xhh460.dao" /> </mappers > </configuration >
webapp.MEAT-INF.content.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?xml version="1.0" encoding="UTF-8"?> <Context > <Resource name ="jdbc/eesy_mybatis" type ="javax.sql.DataSource" auth ="Container" maxActive ="20" maxWait ="10000" maxIdle ="5" username ="root" password ="admin@123" driverClassName ="com.mysql.jdbc.Driver" url ="jdbc:mysql://localhost:3306/user_db" /> </Context >
目前我们把数据库交给tomcat服务器管理了,在程序代码中我们提供配置文件就得到了注册的信息,而且如果注册的东西有变,比如更换了数据库,我们只需要修改注册信息,名称不改,因此代码也不需要修改。
index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <%@ page import ="java.io.InputStream" %> <%@ page import ="org.apache.ibatis.io.Resources" %> <%@ page import ="org.apache.ibatis.session.SqlSessionFactoryBuilder" %> <%@ page import ="org.apache.ibatis.session.SqlSessionFactory" %> <%@ page import ="org.apache.ibatis.session.SqlSession" %> <%@ page import ="com.xhh460.dao.IUserDao" %> <%@ page import ="com.xhh460.entity.User" %> <%@ page import ="java.util.List" %> <%@ page contentType="text/html;charset=utf-8" language="java" %> <html> <body> <h2>Hello World!</h2> <% InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(in); SqlSession sqlSession = factory.openSession(); IUserDao userDao = sqlSession.getMapper(IUserDao.class ) ; List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } sqlSession.close(); in.close(); %> </body> </html>
控制台输出:
Mybatis延迟加载 问题:
在一对多中,当我们有一个用户,该用户有100个账户。
在查询用户的时候,要不要把关联的账户查出来?
在查询账户的时候,要不要把关联的用户查出来?
在查询用户时,用户下的账户信息应该是,什么时候使用,是么时候查询。
在查询账户时,账户的所属用户信息应该是随着账户查询一起查询出来的。
什么是延迟加载?
在真正使用数据的时候才发起查询,不用的时候不查询。按需加载(懒加载)
什么是立即加载?
不管用不用,只要一调用方法,马上发起查询
在对应的四种表关系中:一对多,多对一,一对一,多对多。
一对多,多对多:通常情况下我们都是采用延迟加载。
多对一,一对一:通常情况下我们都是采用立即加载。
一对一方式(一个账户对一个用户)
不开启延迟加载的时候:
开启延迟加载时:
只有在调用的时候,才会进行sql语句的查询
一对多方式(一个用户有多个账户) IAccountDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.xhh460.dao;import com.xhh460.entity.Account;import java.util.List;public interface IAccountDao { List<Account> findAll () ; List<Account> findAccountByUid (Integer uid) ; }
IAccountDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?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.xhh460.dao.IAccountDao" > <resultMap id ="accountUserMap" type ="com.xhh460.entity.Account" > <id property ="id" column ="id" /> <result property ="uid" column ="uid" /> <result property ="money" column ="money" /> <association property ="user" column ="uid" javaType ="com.xhh460.entity.User" select ="com.xhh460.dao.IUserDao.findById" /> </resultMap > <select id ="findAll" resultMap ="accountUserMap" > select * from account </select > <select id ="findAccountByUid" resultType ="com.xhh460.entity.Account" > select * from account where uid = #{uid} </select > </mapper >
Mybatis缓存 什么是缓存?
存在于内存中的临时数据。像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提 高性能。
什么样的数据能使用缓存,什么样的数据不能使用?
适用于缓存的数据:
经常查询并且不经常改变的。
数据的正确与否最终对结果影响不大的
不适用于缓存的数据:
经常改变的数据。
数据的正确与否对最终结果影响很大的。如:商品的库存,银行的汇率,股市的牌价。
Mybatis中的一级缓存 一级缓存:
指的是Mybatis中SqlSession对象的缓存。当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供的一块区域中。该区 域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去SqlSession中查看是否有,有的话直接拿出来用。当SqlSession对 象消失的时候,Mybatis的一级缓存也就消失了。
只要清楚了一级缓存之后,对象就不相等了。
Mybatis中的二级缓存 它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
二级缓存使用步骤:
1.在SqlMapConfig.xml中配置
2.让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
3.让当前的操作支持二级缓存(在select标签中配置)
原理:
测试文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package com.xhh460.test;import com.xhh460.dao.IUserDao;import com.xhh460.entity.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 SecondLevelTest { private InputStream in; private SqlSessionFactory factory; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); factory = new SqlSessionFactoryBuilder().build(in); } @After public void destroy () throws IOException { in.close(); } @Test public void testFindAll () { SqlSession sqlSession = factory.openSession(); IUserDao dao = sqlSession.getMapper(IUserDao.class ) ; User user = dao.findById(6 ); System.out.println(user); sqlSession.close(); SqlSession sqlSession2 = factory.openSession(); IUserDao dao2 = sqlSession2.getMapper(IUserDao.class ) ; User user2 = dao2.findById(6 ); System.out.println(user2); sqlSession2.close(); System.out.println(user.hashCode() == user2.hashCode()); } }
Myabtis注解开发 CRUD注解开发 java.com.xhh460.dao.IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package com.xhh460.dao;import com.xhh460.entity.User;import org.apache.ibatis.annotations.Delete;import org.apache.ibatis.annotations.Select;import java.util.List;public interface IUserDao { @Select ("select * from user" ) List<User> findAll () ; @Delete ("delete from user where id=#{id}" ) void deleteUser (Integer userId) ; @Select ("select * from user where id = #{id}" ) User findUserId (Integer userId) ; @Select ("select * from user where username like #{username}" ) List<User> findUserByName (String username) ; @Select ("select count(*) from user" ) int findTotalUser () ; }
java.com.xhh460.entity.User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package com.xhh460.entity;import java.io.Serializable;import java.util.Date;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId () { return id; } public String getUsername () { return username; } public Date getBirthday () { return birthday; } public String getSex () { return sex; } public String getAddress () { return address; } public void setId (Integer id) { this .id = id; } public void setUsername (String username) { this .username = username; } public void setBirthday (Date birthday) { this .birthday = birthday; } public void setSex (String sex) { this .sex = sex; } public void setAddress (String address) { this .address = address; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}' ; } }
测试文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 package com.xhh460.test;import com.xhh460.dao.IUserDao;import com.xhh460.entity.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 MybatisAnnoTest { private InputStream in; private SqlSessionFactory factory; private SqlSession session; private IUserDao userDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); userDao = session.getMapper(IUserDao.class ) ; } @After public void destroy () throws IOException { session.close(); in.close(); } @Test public void testFindAll () { List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } } @Test public void testDelete () { userDao.deleteUser(6 ); } @Test public void testFindOne () { User user = userDao.findUserId(6 ); System.out.println(user); } @Test public void findByName () { List<User> users = userDao.findUserByName("%小%" ); for (User user : users){ System.out.println(user); } } @Test public void findTotal () { int total = userDao.findTotalUser(); System.out.println(total); } }
如果实体类属性和数据库表字段不对应,可以通过注解这样解决
对于以上注解中的value属性,当只有一个属性的时候,我们可以省去value=
。
一对一查询注解开发 java.com.xhh460.dao.IAccountDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.xhh460.dao;import com.xhh460.entity.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 { @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.xhh460.dao.IUserDao.findByUserId" , fetchType = FetchType.EAGER)) }) List<Account> findAll () ; }
一对多查询注解开发 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package com.xhh460.dao;import com.xhh460.entity.User;import org.apache.ibatis.annotations.*;import org.apache.ibatis.mapping.FetchType;import java.util.List;public interface IUserDao { @Select ("select * from user" ) @Results (id = "userMap" ,value = { @Result (id = true ,column = "id" ,property = "id" ), @Result (column = "username" ,property = "username" ), @Result (column = "address" ,property = "address" ), @Result (column = "sex" ,property = "sex" ), @Result (column = "birthday" ,property = "birthday" ), @Result (property = "accounts" ,column = "id" ,many = @Many (select = "com.xhh460.dao.IAccountDao.findAccountByUid" ,fetchType = FetchType.LAZY)) }) List<User> findAll () ; @Select ("select * from user where id = #{id}" ) User findByUserId (Integer userId) ; @Select ("select * from user where username like #{username}" ) List<User> findUserByName (String username) ; }
注解开发使用二级缓存