MyBatista_log4j

本文详细介绍MyBatis环境搭建步骤、核心配置文件解析及基本CRUD操作实现方法。涵盖参数传递、动态SQL、结果映射、缓存机制等高级特性,并提供分页查询、日志配置等实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搭建开发环境

    添加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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值