文章目录
mybatis中的连接池
mybatis连接池提供了3种方式的配置:
- 主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
type属性的取值:
- POOLED 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
-
UNPOOLED
采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。 -
JNDI 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。(注意:如果不是web或者maven的war工程,是不能使用的。
我们课程中使用的是tomcat服务器,采用连接池就是dbcp连接池。)
autocommit 自动提交
可以在生产session时调用SqlSession openSession(boolean var1) 方法来实现自动提交
即将session=sqlSessionFactory.openSession();
改为session=sqlSessionFactory.openSession(true);
这时完成后就无需进行手动提交了
事务
https://www.cnblogs.com/dongguangming/p/12846052.html
resultmap
https://blog.csdn.net/weixin_44306005/article/details/88100858
mybatis标签
if和where
如果我们想实现根据已有的条件来查询用户的功能,就可以使用if和where标签
例:List finddataUser(User user);
<select id="finddataUser" resultType="com.gegege.domain.User" parameterType="com.gegege.domain.User"> select * from user <where> <if test="username != null "> and username = #{username} </if> <if test="sex != null"> and sex = #{sex} </if> </where> </select>
foreach
有时我们会想要实现下面这样的语句
select * from user where id in (41,42,43,44,45,46);
我们可以定义一个实体类叫queryvo里面存放list< integer>类型的list
dao接口中添加
List<User> getListFindUser(User user);
更改IUserDao.xml
<resultMap id="usermap" type="com.gegege.domain.User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> </resultMap>
<select id="getListFindUser" resultMap="usermap" parameterType="com.gegege.domain.QuertyVo"> select * from user <where> <if test="idList != null and idList.size() != null"> <foreach collection="idList" item="id" open="and id in ( " close=")" separator=","> #{id} </foreach> </if> </where> </select>
编写test函数:
/** * 测试foreach */ @Test public void testforeach() { List<Integer> list=new ArrayList<Integer>(); QuertyVo vo = new QuertyVo(); list.add(41); list.add(42); list.add(43); list.add(44); list.add(45); list.add(46); vo.setIdList(list); List<User> list2=dao.getListFindUser(vo); list2.forEach(System.out::println); } }
SQL标签
对于重复的SQL语句我们可以采用
<sql id="select*"> select * from user</sql>
此标签来进行定义
在需要调用时使用
<include refid="select*"></include>
此语句进行调用
多表查询
先了解一下表之间的关系
先了解一下测试用的数据库
数据库分为用户数据库User:
账户数据库account:
其中account.uid的外键设置为User.id
那么我们先做好准备工作:
1.创建javabean
2.创建IAccountDao接口
一对一操作
如果我们在查找Account时,也需要一并找到对应用户的姓名地址
这时我们可以写出下面这样的sql语句
SELECT a.* , u.username,u.address FROM account a, user u where u.id = a.uid
便可以查询到需要的数据
但这时没有用来存储返回数据的对象
所以我们要创建一个新的javabean
此时便可以配置xml来进行接口的实现
<select id="FindAllAccountUser" resultType="com.gegege.domain.AccountUser"> SELECT a.* , u.username,u.address FROM account a, user u where u.id = a.uid </select>
这时就可以尝试调用
private InputStream in; private SqlSession session; private IAccountDao dao; @Before public void before() throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); session= builder.build(in).openSession(true); dao=session.getMapper(IAccountDao.class); } @After public void after() throws IOException { in.close(); session.close(); } /** * 查找所有账户及对应用户的姓名地址 */ @Test public void FindAllAccountUser() { List<AccountUser> list=dao.FindAllAccountUser(); list.forEach(System.out::println); }
此时便可以获得结果:
一对多操作
由上面两表可知 一个用户可以拥有多个账户,这便是一对多的关系
我们怎么实现一对多的查询呢
同样我们先写出sql语句
SELECT u.*,a.ID as aid,a.UID , a.MONEY FROM user u LEFT JOIN account a on u.id = a.UID
同样我们也需要存储的容器,
在user的javabean中添加一个list即可
private List<Account> list;
更改xml文件
<resultMap id="selectUserAccount" type="com.gegege.domain.User"> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="birthday" column="birthday"></result> <result property="sex" column="sex"></result> <result property="address" column="address"></result> <collection property="list" ofType="com.gegege.domain.Account"> <id column="aid" property="id"></id> <result column="uid" property="uid"></result> <result column="money" property="money"></result> </collection> </resultMap> <select id="findAll" resultMap="selectUserAccount"> SELECT u.*,a.ID as aid,a.UID , a.MONEY FROM user u LEFT JOIN account a on u.id = a.UID </select>
测试一下
private InputStream in; private SqlSessionFactoryBuilder sessionFactoryBuilder; private SqlSessionFactory sqlSessionFactory; private SqlSession session; private IUserDao dao; @Before public void before() throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml"); //创建工具 sessionFactoryBuilder=new SqlSessionFactoryBuilder(); //创建工厂 sqlSessionFactory=sessionFactoryBuilder.build(in); //生产session session=sqlSessionFactory.openSession(); //使用sqlsession 创建代理对象 dao=session.getMapper(IUserDao.class); } @After public void after() throws IOException { //提交操作 session.commit(); //释放资源 session.close(); in.close(); } /** * 测试查找 * @throws IOException */ @Test public void testFindAll() { //调用findall List<User> users=dao.findAll(); for (User user:users ) { System.out.println(user+""+user.getList()); } }
输出结果为:
多对多操作
按照步骤来建立数据库
建立完成后有这样三个表
1.角色表(role):
2.用户表(user):
3.中间表(user_role):
UID的外键是user表中的id
RID的外键是角色表中的ID
和一对多操作相同,我们想要查询用户表时可以查询到对应角色相关信息
查询角色表时可以查询到对应用户相关信息
可以写出sql语句:
SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r right JOIN user_role ur ON rid = r.id right JOIN user u ON uid = u.id
SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r LEFT JOIN user_role ur ON rid = r.id LEFT JOIN user u ON uid = u.id
有了sql语句则需要存储查询结果
则在user的javabean中和role的javabean中添加彼此的list用来存储
之后声明resultMap
<resultMap id="Rolemap" type="com.gegege.domain.Role"> <id property="roleid" column="rid"></id> <result property="rolename" column="ROLE_NAME"></result> <result property="roledesc" column="ROLE_DESC"></result> <collection property="users" ofType="com.gegege.domain.User"> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="birthday" column="birthday"></result> <result property="sex" column="sex"></result> <result property="address" column="address"></result> </collection> </resultMap>
<resultMap id="usermap" type="com.gegege.domain.User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <collection property="roles" ofType="com.gegege.domain.Role"> <id property="roleid" column="rid"></id> <result property="rolename" column="ROLE_NAME"></result> <result property="roledesc" column="ROLE_DESC"></result> </collection> </resultMap>
声明sql查询
<select id="findAll" resultMap="Rolemap" > SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r LEFT JOIN user_role ur ON rid = r.id LEFT JOIN user u ON uid = u.id </select>
<select id="findAll" resultMap="usermap" > SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r right JOIN user_role ur ON rid = r.id right JOIN user u ON uid = u.id </select>
扩展:JNDI
jndi类似于windows中的注册表,存储了键值对
需要注意项目需要时war工程 且经过tomcat服务器才可以运行
首先,将之前mybatis的工程复制过来
配置javaweb环境:
添加下面两个jar包即可
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> </dependency>
配置JNDI环境:
– 1.在webapp文件夹下创建META-INF文件夹
– 2.在文件夹下创建context.xml文件
– 3.将以下配置内容添加到context.xml
<?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="1234" 密码 driverClassName="com.mysql.jdbc.Driver" 驱动类 url="jdbc:mysql://localhost:3306/eesy_mybatis" 连接url字符串 /> --> <Resource name="jdbc/mybatis" type="javax.sql.DataSource" auth="Container" maxActive="20" maxWait="10000" maxIdle="5" username="root" password="adminadmin" driverClassName="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://localhost:3306/mybatis" /> </Context>
– 4.更改SqlMapConfig.xml
将原来存放数据库url密码等信息的位置更改为
这里要注意:“java:comp/env/”这段是固定的,而后面内容为自己定义的名称
<dataSource type="JNDI"> <property name="data_source" value="java:comp/env/jdbc/mybatis"/> </dataSource>**
此时执行test便发现会报错
因为要使用JNDI是需要经过服务器的
这时就要用到jsp来连接数据库
<%@ page import="org.apache.ibatis.io.Resources" %> <%@ page import="org.apache.ibatis.session.SqlSessionFactoryBuilder" %> <%@ page import="com.gegege.dao.IUserDao" %> <%@ page import="com.gegege.domain.User" %> <%@ page import="java.util.List" %> <%@ page import="java.io.InputStream" %> <%@ page import="org.apache.ibatis.session.SqlSessionFactory" %> <%@ page import="org.apache.ibatis.session.SqlSession" %> <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="utf-8" %> <html> <body> <% InputStream in; SqlSessionFactoryBuilder sessionFactoryBuilder; SqlSessionFactory sqlSessionFactory; SqlSession session2; IUserDao dao; in = Resources.getResourceAsStream("SqlMapConfig.xml"); //创建工具 sessionFactoryBuilder=new SqlSessionFactoryBuilder(); //创建工厂 sqlSessionFactory=sessionFactoryBuilder.build(in); //生产session session2=sqlSessionFactory.openSession(); //使用sqlsession 创建代理对象 dao=session2.getMapper(IUserDao.class); //调用findall List<User> users=dao.findAll(); for (User user:users ) { System.out.println(user); } //提交操作 session2.commit(); //释放资源 session2.close(); in.close(); %> </body> </html>
此时运行打开index.jsp
便会发现控制台输出了数据库中的数据