文章目录
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
便会发现控制台输出了数据库中的数据