文章目录
说明
因为是个人复习java的总结,所以结构稍显杂乱,有些语句过于口语化.
连接池
连接池的概念就跟线程池之前使用的druid概念相同.
三种Mybatis连接池
POOLED
使用数据库带的数据库连接池,是在DataSource
的基础上,自己实现的数据库连接池.整体上思路还是差不多,就是初始化连接池,然后从空闲池获取连接,存入运行池.
UNPOLLED
不适用数据库连接池,也就是使用DataSource
进行获取数据库连接,获取思路没什么好说的,就是获取驱动,propertyies
读取配置文件,然后获取Connection
.
JNDI
根据Web使用的服务器获取不同的数据库连接池.这种模式需要服务器才能采用.
Mybatis中的事务
之前在简单地使用Myabtis的提交更新的时候,其实就是在使用工厂获取Session
连接的时候,没有设置事务的模式,然后就导致了需要手动提交事务.可以在openSession()
方法中传入参数作为事务的自动提交模式开启.
多条件连接问题
在使用xml配置实现查询的时候,前面单纯配置sql语句的方式,其实存在传入参数中缺少某个条件导致出现语句错误的问题.这个问题明显不应该暴露给用户.
可以使用在<select>
标签中添加<if>
和<where>
解决这个问题.其实就是对于设置的sql语句添加一个数据判断,如果判断通过,再将<if>
中的sql语句添加到外部语句的后面.
而<where>
是用来解决多条件组合的时候第一个条件去除and和or,其实自己在上面的sql语句中添加where 1=1
也可以解决.实例如下
<select ...这里省略了传参,结果之类的内容>
select * from person
<where>
<if test="name != null">
and name = #{name};
</if>
</where>
</select>
另外需要注意一点if中的条件判断内容,是用and,or来连接的.
实现类集合对应in多参数判断问题
其实就是针对sql中类似select * from person where id in (1,2,3)
这样的sql语句的时候,传入的in中数据一般会以集合的形式表现实体类中.
可以使用<foreach>
标签来实现对于集合的遍历添加,实例如下:
<select>
select * from person
<where>
<if test = "ids != null and ids.size()>)">
<foreach collection="ids" open="and id in (" close=")" item="id" spector=",">
#{id}
</foreach>
</if>
</where>
</select>
具体内容没什么好理解的,看语句中的参数都可以理解如何实现.
include 标签
可以用来实现xml中sql语句的复用,需要配合<sql>
标签来使用,实例如下:
<sql id="default">
select * from person
</sql>
<select>
<include refid="default"></include>
</select>
Mybatis的多表查询一对一
其实就是针对数据库的多表查询会形成新的表,但是对于返回的数据,在xml的配置中,上面是通过返回某个类型的数据然后输出的,但是形成新的表之后,这个返回类型就会出现问题.
最简单的解决方式就是根据多表查询的语句去创建新的实体类,这样就可以正确的返回数据,但是显然这种方式的开发效率实在实在是比较低.
另外一种方式,就是通过xml的配置和实体类属性设置的优化来解决问题.比如说针对多表查询sql语句
select u.*,a.id as aid ,a.uid,a.money
from account a, user u
where u.id = a.uid;
其实上面的sql语句表达的就是通过用户表的id和账户表的用户id进行匹配,查询生成结果用户所有信息,加上账户信息的id.
这个语句如果使用上面的写新的子类的方式实现的话,那就需要生成具有特定属性的类.
如果使用xml的方式配置的话,首先需要优化账户表,账户表中需要添加一个用户表的实体类作为属性.然后就可以在xml中设置resultMap来实现特定的返回数据.
<!-- 定义封装account和user的resultMap -->
<resultMap id="accountUserMap" type="account">
<!-- 配置account的属性和数据库字段的映射关系,也就是account属性和查询结果表的对应 -->
<id property="id" column="aid"><id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!-- 一对一的映射关系,配置封装的user的内容 -->
<association>
<id property="id" column="id"><id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
</association>
</resultMap>
<select id="findAccountUserMap" resultMap="accountUserMap">
select u.*,a.id as aid ,a.uid,a.money from account a, user u where u.id = a.uid;
</select>
整体上就是这么实现,但是需要注意这时候返回的其实还是account
的对象,只是在account
对象中设置了user
属性,所以可以将数据一一对应的封装到account
和其中的user
中去.输出的时候可以通过account
对象获取user
对象.
一对多的多表查询
其实和一对一的实现方式也很像,只是在对于实体类的定义中,需要加入的不再是外键对应的表的实体类,而是这个实体类的集合.然后就是在resultMap
中进行相关配置.
比如说对于上面一对一的数据库,也就是一个user
用户对应多个account
信息的时候,就可以在user
实体类中添加一个对于account
的集合.
然后就是配置resultMap
,之前一对一的时候可以使用<assocition>
标签,但是现在是集合,所以需要使用<collection>
标签来添加数据.实例如下:
<resultMap id="userAccountMap" type="user">
<!-- 设置用户的基础信息对应关系 -->
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!-- 设置对于账户信息的集合数据对应关系 -->
<collection property="accounts" ofType="account"> <id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
</collection>
</resultMap>
然后设计一下具体的sql语句,根据上面的设计,我们需求的是所有的用户信息,并且需要存在账户信息的用户后面跟上账户信息.那么就可以使用左外连接,将用户信息全部添加,然后根据账户信息,给存在账户信息的用户添加信息.也就是:
select * from user u left outer join account account a on u.id=a.id;
多对多的多表查询
其实就是基于上面的一对多的实现,双向实现了而已,这里主要注意的就是sql语句的编写.以用户表和角色表为例,用户和角色实体类中的集合都已经设置好,resultMap
也配置好.这里唯一的问题就是,如何查询出用户或者角色对应的多关系数据.如果是像上面一样的简单表,那实现很简单.
但是这个问题的本质在于关系型数据库表的设计一般不会像上面那样设计.像学生和选课,一般都是分为学生表,选课表,两者对应关系表.我也忘了这是属于第几范式的要求.但是如果出现这样的状况的sql语句实现,还是比较麻烦的.实例如下:
select u.*,r.id as rid,r.role_name,r.row_desc from role r
left outer join user_role ur on r.id = u.id
left outer join user u on u.id=ur.uid;
可以理解一下上面的sql,其实就是首先通过role
表,左外连接对应表中的user
的id
,然后再对形成的新表使用左外连接user
对应的数据信息.
JNDI
上面提到了动态配置数据库连接的方式,但是没有使用,这里简单应用一下,就用之前用过的Tomcat和Mysql配置…
- 在Tomcat安装目录下的
conf/
创建一个context.xml
配置文件,书写配置文件
<Resource name="jndi/mysql"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://ip:port/dbName?useUnicode=true&characterEncoding=UTF-8"
username="root"
password="root"
maxActive="20"
maxIdle="10"
maxWait="10000"/>
具体内容根据不同的数据库不同,注意url中的连接符号,因为解析方式的不同需要不同的书写.
- 修改Mybatis主配置的dataSource信息
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/上面配置的name"></property>
</dataSource>
如有错误欢迎读者批评指正!!