搭建开发环境
添加jar包
mybatis-3.1.1.jar...
添加并编写总配置文件(在src根目录下) mybatis-config.xml
<?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="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" />
<property name="username" value="ami" />
<property name="password" value="ami" />
</dataSource>
</environment>
</environments>
<mappers> <!-- //用来配置dao.xml文件 -->
<mapper resource="dao/XxxMapper.xml" />
</mappers>
</configuration>
### 编写XxxMapper.xml (dao层)
<?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="dao.XxxDao">
<XXX id="xxx" resultType="返回值类型" parameterType="参数类型">
</XXX>
</mapper>
Xxx.java
//创建SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession session = build.openSession();
session.XXX(String xxx,Object o);
---------------------------------------------
Mybatis格式化<符号
<![CDATA[]]>
Mybatis配置提示文件
复制mybatis-3-mapper.dtd
封装MyBatisUtil.java
//大前提:jdbc中的Connection 约等于 MyBatis中的 SqlSession
public class MyBatisUtil {
//一:全局声明一个ThreadLocal 保证SqlSession对象是同一个
private static ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();
private static SqlSessionFactory sqlSessionFactory;
//二:静态代码块做初始化操作(加载一次的操作) 加载mybatis-config.xml
static{
try {
//以数据流的方式读取总配置文件(mybatis-config.xml)
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//创建一个SqlSessionFactory(工厂)
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("初始化MyBatis失败");
}
}
//三:提供一个方法 获取数据库连接
public static SqlSession getSqlSession(){
/怎么创建SqlSession的对象
SqlSession session = tl.get(); //1.先从tl中获取SqlSession
//2.如果session为null则创建并存储tl里面,否则直接返回使用
if(session == null){
session = sqlSessionFactory.openSession();
tl.set(session);;
}
return session;
}
//四:关闭SqlSession
public static void close(){
//1.获取你要想关闭的SqlSession
SqlSession session = tl.get();
//2.如果session不能null,代表可以有被关闭的session ,并从tl中移除
if(session != null){
session.close();
tl.remove();
}
}
}
传递多个参数
用Map
java:
map.put(key,value)
XxxMapper.xml:
<select id="" parameterType="java.util.Map" resultType="">
#{key} <!-- 通过key找value -->
</select>
接口
1).规范一些任务
2).依赖于接口,减少类于类之间的耦合
先写接口,再写实现类
XxxServiceImpl 实现 XxxService(业务逻辑层的接口)
XxxDaoImpl 实现 XxxDao(数据库访问层的接口)
MyBatis 只写接口 ,不写实现类,需要遵循两个规则。使用代理模式(框架内部运行时,帮助生成实现类,即代理类)
1.dao接口中的方法名要和mapper.xml文件中的id名保持一致
2.namespace的值 需要是对应接口 的 全路径
XxxBiz:
SqlSession session = MyBatisUtil.getSqlSession();
XxxDao dao = session.getMapper(XxxDao.class); //利用反射
resultMap
实体类的属性名 和 数据库表的列名 名称不一致时:
<resultMap type="" id="">
<!-- column数据库的字段名
property实体类的属性-->
<result column="" property=""/>
</resultMap>
<select id="" resultMap="">
<!-- SQL语句 -->
</select>
-----------------------------------------------
对列名起别名
抽取重复的sql语句(动态sql)
<!-- 标签中有一些sql语句重复 使用sql标签 提取重复的sql语句-->
<sql id="a">
select * from dept
</sql>
<select id="" parameterType="" resultType="">
<include refid="a"/> where id = 100
</select>
多条件查询(动态sql)
有些查询条件可能没有数据
例如:用户有可能查询部门编号和部门名称,也有可能查询全部
<!-- 模糊查询把%作为字符串拼接 oracle字符串拼接用 || -->
<select id="" parameterType="" resultType="">
select * from dept
<where>
<if test="a!=null">
department_id > 100
</if>
<if test="b!=null"> <!-- 后面的if用and -->
and department_name like '%'||e||'%'
</if>
</where>
</select>
---------------------------------------------------------------------------
<select id="" parameterType="" resultType="">
select * from dept where 1=1
<if test="a!=null">
and department_id > 100
</if>
<if test="b!=null">
and department_name like '%'||e||'%'
</if>
</select>
批量删除(动态sql)
<delete id="">
delete from tableName where id in
<!-- collection规范参数类型
open开始的符号
close结束的符号
separator分隔符
item要循环的数据 -->
<foreach collection="array" open="(" close=")" separator="," item="sid">
#{sid}
</foreach>
</delete>
分页(重点)(动态sql)
Xxxmapper.xml
<!-- 分页查询 -->
<select id="selectAllProduct" resultType="com.entity.Product" parameterType="java.util.Map">
select * from(
select t.*,rownum rn from(
select * from t_product <!-- // 最内层 -->
) t where rownum <![CDATA[ <= ]]> #{end} <!-- 控制最大 -->
) where rn > #{start} <!-- 控制最小 -->
</select>
<!-- 查询数据库的总条数 -->
<select id="selectProductCount" resultType="java.lang.Integer">
select count(1) from t_product
</select>
XxxDao
//分页查询
public List<Product> selectAll(Map map) {
SqlSession session = MyBatisUtil.getSqlSession();
List<Product> products = session.selectList("selectAllProduct",map);
return products;
}
//查询数据库的总条数
public int selectProductCount(){
SqlSession session = MyBatisUtil.getSqlSession();
int count = session.selectOne("selectProductCount");
return count;
}
XxxService
//分页查询
public List<Product> getAllProduct(Map map){
List<Product> products = dao.selectAll(map);
MyBatisUtil.close();
return products;
}
//查询数据库的总条数
public int getProductCount(){
int count = dao.selectProductCount();
MyBatisUtil.close();
return count;
}
XxxAction
private Integer pageIndex; //页数 //Action属性
private Integer pageSize = 5; //每页几条
private Integer pageCount; //总页数
//分页
public String showAllProduct(){
Map map = new HashMap();
ProductBiz biz = new ProductBiz();
int count = biz.getProductCount(); //得到总条数
//根据总条数和每页显示条数 计算总页数(三目运算符)
pageCount=(count%pageSize==0)?(count/pageSize):(count/pageSize+1);
if(pageIndex==null || pageIndex<=0){ //默认显示第一页/点击上一页直至第一页
pageIndex=1;
}else if(pageIndex>=pageCount){ //点击下一页直至总页数(最后一页)
pageIndex=pageCount;
}
map.put("start", (pageIndex-1)*pageSize); //为了在xml文件中 通过key来找value
map.put("end", pageIndex * pageSize);
list = biz.getAllProduct(map);
return "showAllProduct";
}
Xxx.jsp
<a href="/项目名/product_showAllProduct?pageIndex=1">[首页]</a>
<a href="/项目名/product_showAllProduct?pageIndex=<s:property value='pageIndex-1'/> ">[上一页]</a>
<a href="/项目名/product_showAllProduct?pageIndex=<s:property value='pageIndex+1'/> ">[下一页]</a>
<a href="/项目名/product_showAllProduct?pageIndex=<s:property value='pageCount'/> ">[尾页]</a>
当前是<s:property value='pageIndex'/>页/共<s:property value='pageCount'/>页
不确定更新(动态sql)
<update id="" parameterType="">
update dept
<set>
<if test="a!=null">
department_name = 'name'
</if>
<if test="b!=null">
local_id = 10024
</if>
</set>
where department_id = 100
</update>
类与类之间的关系
一对一 //护照--乘客
class Passort {
……
Passenger passenger;
}
<!-- result标签 column 数据库的字段名 property 实体类的属性 -->
<!-- id标签和result标签用法相同 用来处理主键字段 -->
<resultMap type="entity.Passort" id="passortResultType">
<id column="id" property="id"/>
<result column="nationality" property="nationality"/>
<association property="passenger" javaType="entity.Passenger">
<id column="pid" property="id"/>
<result column="name" property="name"/>
</association>
</resultMap>
<select id="selectPassort" resultMap="passortResultType">
<!-- 多表连接查询有相同的字段名,需要在查询语句中起别名来区别,如t2.id as pid -->
select t1.id , t1.nationality , t2.id pid , t2.name ,
from t_passort t1 left join t_passenger t2 on mm
</select>
多对一 [重点] //员工--部门
class Emp{
……
Dept dept;
}
<resultMap type="entity.Emp" id="empDept">
<result column="employee_id" property="employee_id"/>
<result column="first_name" property="first_name"/>
<!-- property是Emp实体类中Dept的属性名dept
javaType 数据要被封装到哪个实体类 -->
<association property="dept" javaType="entity.Dept">
<result column="department_id" property="department_id"/>
<result column="department_name" property="department_name"/>
</association>
</resultMap>
<select id="" resultMap="empDept">
select * from employees e
left join departments d
on e.department_id=d.department_id
where e.employee_id=100
</select>
一对多 //部门--员工
class Dept{
……
List<Emp> emps;
}
<resultMap type="entity.Dept" id="deptResultMap">
<id column="department_id" property="department_id"/>
<result column="department_name" property="department_name"/>
<!-- xxx对一用 association 连接-->
<!-- xxx对多用 collection 连接 -->
<!-- collection 处理多的一方的数据 property 写Dept中集合的对象名 ofType 集合中元素的实际类型 -->
<collection property="emps" ofType="entity.Emp">
<id column="employee_id" property="employee_id"/>
<result column="first_name" property="first_name"/>
</collection>
</resultMap>
<select id="selectDeptById" resultMap="deptResultMap" parameterType="java.lang.Integer">
select * from departments t1
left join employees t2 on t1.department_id = t2.department_id
where t1.department_id = 100
</select>
多对多 //学生-- --选修课
多对多,在数据库中需要创建第三方表,以学生表和选修课表作为联合主键
但在实体类中,则不需要创建第三方实体类,因为实体类是用来存储对象的
多对多可以通过第三方表看作是两个一对多或多对一(表连接)
MyBatis缓存:
缓存可以减少访问数据的频率,因为数据可以直接从内存中读取
1.在总配置文件中(mybatis-config.xml)启用缓存
<settings>
<setting name='cacheEnabled' value='true'/>
</settings>
2.开启某一个mapper的缓存
<cache /> 其中的属性都有默认值
flushInterval='缓存有效期(毫秒)'
3.实体类实现 Serializable 接口(序列化)
添加数据的一些小细节
添加了一条数据,需要返回该数据的id编号
<insert id="insertStudent" parameterType="entity.Student">
<!-- keyProperty 存储selectKey标签的查询结果 (把结果赋值给变量id)----需要在实体类中存在,否则报错 -->
<!-- order (BEFORE 在……之前) selectKey中的sql语句先执行 -->
<!-- resultType 查询结果的返回值类型 -->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Integer">
select seq_student.nextval from dual
</selectKey>
insert into t_student(id,name,age)
values(#{id},#{name},#{age})
</insert>
添加空值问题
<!-- 例如注册的时候,有些值允许为null -->
<insert id="insertStudent2" parameterType="entity.Student">
insert into t_student(id,name,age)
<!-- jdbcType=枚举 -->
values(#{id},#{name,jdbcType=VARCHAR},#{age,jdbcType=INTEGER})
</insert>
Log4j配置 (log for java)
导包:
log4j-1.2.16.jar
slf4j-api-1.6.2.jar
slf4j-log4j12-1.6.2.jar
编写配置文件
log4j.properties
放在src下的话就不用配置 否则得去web.xml里面配置一个Listener
Log4j说明
og4j.rootCategory=INFO,stdout,R //将等级为INFO的日志信息输出到stdout和R这两个目的地,可以任意起名
等级可分为off、fatal、error、warn、info、debug、all
如果配置OFF则不打出任何信息
如果你的配置文件中配置的级别是debug,那么error warn info debug 都会显示
如果你的配置文件中配置的级别是info,那么error warn info会显示
如果你的配置文件中配置的级别是warn,那么error warn会显示
如果你的配置文件中配置的级别是error,那么error会显示
log4j.appender.stdout= //此句为定义名为stdout的输出端是哪种类型,包括
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
log4j.appender.stdout.layout= //此句为定义名为stdout的输出端的layout是哪种类型,包括
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
log4j.appender.stdout.layout.ConversionPattern= //如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为"rn",Unix平台为"n"
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy MMM dd HH:mm:ss,SSS}
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。
[?]是log信息的开头,可以为任意字符,一般为项目简称。
log4j.appender.R.File=xxx.log //定义名为R的输出端的文件名为……可以自行修改
log4j.logger.com.neusoft=DEBUG //指定com.neusoft包下的所有类的等级为DEBUG。
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR
这两句是把这两个包下出现的错误的等级设为ERROR,如果项目中没有配置EHCache,则不需要这两句。
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
这两句是struts的包。
log4j.logger.org.displaytag=ERROR
这句是displaytag的包。(QC问题列表页面所用)
log4j.logger.org.springframework=DEBUG
此句为Spring的包。
log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
此两句是hibernate的包。
MyBatis3_用户指南(附JavaDB实例).pdf
mybatis generator的使用
安装:
方式1:站点上直接安装
Help—>install from site…
http://mybatis.googlecode.com/svn/sub-projects/generator/trunk/eclipse/UpdateSite/
方式2:
1. 把plugins中的所有jar拷贝到eclipse的plugins文件夹之中
2. 把features中的所有文件夹拷贝到eclipse的features文件夹之中
3. 重启eclipse,ok
方式3:
将给定的plugins和feaures目录直接拷贝到MyEclipse Professional\dropins
重启myeclipse