spring mybatis整合

spring的声明式事务管理,可以回滚service的操作(当遇到异常情况时)

Class Log{
  Propagation.REQUIRED
  insertLog();
}

Propagation.REQUIRED
void saveDept(){
  insertLog();//加入当前事务
  ..异常部分
  saveDept();
}

Class LOg{
  Propagation.REQUIRED_NEW
   insertLog();
}
  Propagation.REQUIRED
void saveDept(){
  insertLog();//始终开启事务
  ..异常部分,日志不会回滚
  saveDept();
}

Aop,aspect object programming 面向切面编程
功能:让关注点代码与业务代码分离!
关注点
重复代码就叫做关注点;
切面,
关注点形成的类,就叫切面(类)!
面向切面编程,就是指对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。
切入点,
执行目标对象方法,动态植入切面代码。
可以通过切入点表达式,指定拦截哪些类的哪些方法;给指定的类在运行的时候植入切面类代码。(根据需要进行拦截,是否需要拦截)
切入点表达式,
可以对指定的“方法”进行拦截; 从而给指定的方法所在的类生层代理对象。
spring broke up traditionnal model

spring七大模块详解

prefix=“c”C标签的序号显示,varStatus=vs
struts的序号是 prefix=s status=st

spring 代理理解

1.动态代理,用工厂类实现–需要实现接口

1.测试类
ApplicationContext ac = new ClassPathXmlApplicationContext(
“com/coffee/aop/bean.xml”);

   /**
    * 动态代理(jdk代理)
    *
    * @throws Exception
    */
   @Test
   public void testAop() throws Exception {

        // 调用工厂类,获取注解
        IUserDao userDao = (IUserDao) ac.getBean("userDaoProxy");
        // 代理对象:class com.sun.proxy.$Proxy5
        System.out.println(userDao.getClass());
        userDao.save();
   }

2.代理工厂类–用反射实现

@Component(“userDaoProxy”)
public class ProxyFactory {

   private static Object target;
   private static Aop aop;

   public static Object getProxyInstance(Object target_, Aop aop_) {
        target = target_;
        aop = aop_;

        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                 target.getClass().getInterfaces(), new InvocationHandler() {

                      @Override
                      public Object invoke(Object proxy, Method method,
                                Object[] objects) throws Throwable {

                           // 在核心业务代码执行前,,引入重复执行的代码
                           aop.begin();
                           Object returnValue = method.invoke(target, objects);
                           // 核心代码结束后执行收尾工作
                           aop.commit();
                           return returnValue;
                      }
                 });

   }

2.动态代理–不需要使用工厂类,用注解

1.dao层,加注解:@Repository(“userDao”)

@Repository("userDao")
public class UserDao implements IUserDao {

   public void save() {
        // 获取session/处理异常--每次都要重复执行此类代码:被称为【关注点代码:就是重复执行的代码】
        System.out.println("UserDao 核心业务代码:保存数据。。");// 这才是真正的核心业务代码:【关键点代码】
        // 关闭session/处理异常--每次都要重复执行此类代码:【关注点代码:就是重复执行的代码】
   }

2.bean.xml

首先

<context:component-scan base-package="com.coffee.aop"></context:component-scan>

然后开启aop :自动实现代理

<!-- 注解实现 aop编程 -->
<!-- 1.在命名空间引入 aop相关头 -->
<!-- 2.开启 aop注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3.cglib代理:实现的cglib代理的类不能是final
cglib代理:需要引入spring-core.jar文件

1.测试类
/**
* 注解代理:目标类没有实现接口,aop自动执行 cglib代理
*
* @throws Exception
*/
@Test
public void testCglibAop() throws Exception {

          // 调用工厂类
          OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
          // 代理对象:class com.sun.proxy.$Proxy5
          System.out.println(orderDao.getClass());
          orderDao.save();
     }

2.dao层加注解
// 将目标对象加入ioc
@Repository(“orderDao”)
public class OrderDao {// 没有实现接口,使用cglib代理

     public void save() {
          System.out.println("OrderDao 核心业务代码:保存数据。。");// 这才是真正的核心业务代码:【关键点代码】
     }

3.bean.xml配置注解,开启aop

首先 <!-- 开启注解扫描 -->
<context:component-scan base-package="com.coffee.aop"></context:component-scan>

然后开启aop :自动实现代理

<!-- 注解实现 aop编程 -->
<!-- 1.在命名空间引入 aop相关头 -->
 <!-- 2.开启 aop注解 -->
 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

cglib底层实现

public class ProxyFactory_cglib implements MethodInterceptor {

     private Object target;// 维护代理对象

     public ProxyFactory_cglib(Object target) {
          this.target = target;
     }

     // 给目标对象创建代理对象
     public Object getProxyInstance() {
          // 1. 工具类,在引入的jar文件中spring-core.jar
          Enhancer enhancer = new Enhancer();
          // 2. 设置父类
          enhancer.setSuperclass(target.getClass());
          // 3. 设置回掉函数
          enhancer.setCallback(this);
          // 4. 创建子类代理对象,,,,所以使用cglib代理的dao不能是final的
          return enhancer.create();
     }

关注点代码&&关键点代码

dao层

public void save() {
        // 获取session/处理异常--每次都要重复执行此类代码:被称为【关注点代码:就是重复执行的代码】
        System.out.println("UserDao 核心业务代码:保存数据。。");// 这才是真正的核心业务代码:【关键点代码】
        // 关闭session/处理异常--每次都要重复执行此类代码:【关注点代码:就是重复执行的代码】
   }

切入点表达式

bean.xml:

<!-- 配置aop -->
    <aop:config>
      <!-- 定义一个切入点表达式 ,指定拦截哪些类的哪些方法-->
      <aop:pointcut expression="execution(* com.coffee.pointcut.*.*(..))" id="pt"/>

    <!-- 从这开始#######【下面是测试别的方法】######### -->
      <!-- 拦截所有的public方法-->
      <aop:pointcut expression="execution(public * *(..))" id="pt"/>
      <!-- 拦截所有的save方法-->
      <aop:pointcut expression="execution(* save*(..))" id="pt"/>
      <!-- 拦截指定类的指定的指定方法,具体到方法-->
      <aop:pointcut expression="execution(* com.coffee.pointcut.OrderDao.save(..))" id="pt"/>
      <!-- 拦截指定类的指定的所有方法,具体到类-->
      <aop:pointcut expression="execution(* com.coffee.pointcut.OrderDao.*(..))" id="pt"/>
      <!-- 拦截指定包,及其子包下的的所有类的所有方法 -->
      <aop:pointcut expression="execution(* com..*.*(..))" id="pt"/>
      <!-- 【多个表达式】 -->
      <!-- 拦截或的关系的方法,不能用and 或者&& -->
      <aop:pointcut expression="execution(* com.coffee.pointcut.OrderDao.save()) || execution (* com.coffee.pointcut.UserDao.save())" id="pt"/>
      <aop:pointcut expression="execution(* com.coffee.pointcut.OrderDao.save(..))) || execution(* com.coffee.pointcut.UserDao.save())" id="pt"/>
      <!-- 取非值 -->
      <aop:pointcut expression="!execution(* com.coffee.pointcut.OrderDao.save())" id="pt"/>
      <!-- not 前要加空格,和上面等价 -->
      <aop:pointcut expression=" not execution(* com.coffee.pointcut.OrderDao.save())" id="pt"/>
    <!-- 从这结束################ -->
      <!-- 切面配置 -->
      <aop:aspect ref="aop">
          <!-- 环绕通知 -->
          <aop:around method="around" pointcut-ref="pt"/>
          <!-- 前置通知 -->
          <aop:before method="begin" pointcut-ref="pt"/>
          <!-- 后置通知(最终通知) -->
          <aop:after method="after" pointcut-ref="pt"/>
          <!-- 返回后通知 -->
          <aop:after-returning method="afterReturning" pointcut-ref="pt"/>
          <!-- 异常的通知 -->
          <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
      </aop:aspect>

    </aop:config>

aop切面类:

public class Aop {

   public void begin() {
        System.out.println("开始事务/异常");
   }

   public void after() {
        System.out.println("提交事务/关闭");
   }

   public void afterReturning() {

        System.out.println("afterReturning()");
   }

   // 目标方法异常处理
   public void afterThrowing() {

        System.out.println("afterThrowing()");
   }

   public void around(ProceedingJoinPoint pjp) throws Throwable {

        System.out.println("环绕前执行。。相当于@Before()");
        pjp.proceed();
        System.out.println("还绕后执行。。相当于@After()");
   }

}

// 事务传播的属性
@Service
public class T_DeptService {

   @Resource
   // 加入容器
   T_DeptDao t_DeptDao = new T_DeptDao();
   @Resource
   LogsDao logsDao = new LogsDao();

   // 事务传播的属性
   @Transactional(
   // readOnly = false,
   // timeout = -1,
   // noRollbackFor = ArithmeticException.class 遇到异常不回滚
   // propagation=Propagation.REQUIRED Propagation.REQUIRED
   // 指定当前的方法必须在事务的环境下执行;
   // 如果当前运行的方法,已经存在事务, 就会加入当前的事务,受当前事务约束;
   // Propagation.REQUIRED_NEW
   // 指定当前的方法必须在事务的环境下执行;
   // 如果当前运行的方法,已经存在事务: 事务会挂起(就像遇到异常不回滚此方法); 会始终开启一个新的事务,执行完后; 刚才挂起的事务才继续运行。

   )
   // 必须加上这个注解才能实现注解的spring事务控制,这个注解可以加载类上,父类上,范围范围根据加在什么上面而不同
   public void save(T_Dept t_Dept) {

        logsDao.insertlog();
        int i = 1 / 0;// 模拟中间的异常,配置spring事务控制后遇到异常就会回滚,即上面的数据库操作无效
        t_DeptDao.save(t_Dept);
   }

 <!-- 1.【c3p0连接池 数据源配置(oracle)】 -->
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
        <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl"></property>
        <property name="user" value="wangan"></property>
        <property name="password" value="666"></property>
        <property name="initialPoolSize" value="3"></property>
        <property name="maxPoolSize" value="10"></property>
        <property name="maxStatements" value="100"></property>
        <property name="acquireIncrement" value="2"></property>
      </bean>
      <!-- 2.【数据库模板】 -->
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
      </bean>

pring声明式事务管理

<!-- ####5. spring声明式事务管理器### -->
    <!-- 1. 配置事务管理器类 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 2. 配置事务增强 ,如何管理事务-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
      <tx:attributes>
      <!-- 以get开头/find开头的所有方法只读,剩下的读写 -->
          <tx:method name="get*" read-only="true"/>
          <tx:method name="find*" read-only="true"/>
          <tx:method name="*" read-only="false"/>
      </tx:attributes>
    </tx:advice>
    <!-- 3. 配置aop,拦截哪些方法(切入点表达式)+应用上面的事务增强  -->
    <aop:config>
      <aop:pointcut id="pt" expression="execution(* com.coffee.spring_transaction.T_DeptService.*(..))" /><!-- (..)带上两个点;第一个*式返回值类型 -->
      <!-- 引入切入点表达式 -->
      <aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
    </aop:config>

1.mybatis中的sqlsession工具类

package utils;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * 加载mybatis配置文件
 * @author wangan
 *
 */
public class MybatisUtil {

    // 本地线程,用于绑定session,,SqlSession是mybatis里面的创建session的类,hibernate是session
    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

    private static SqlSessionFactory sqlSessionFactory;

    // 私有化无参构造,防止人为不断new他
    private MybatisUtil() {
    }

    // 使用static静态块的好处就是加载快,只能加载一次
    static {
        try {
            // 加载src/mybatis.xml
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            // 加载reader,创建sqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 返回session
     */
    public static SqlSession getSqlSession() {

        SqlSession sqlSession = threadLocal.get();
        if (sqlSession == null) {
            sqlSession = sqlSessionFactory.openSession();
            // 本地线程绑定sqlsession
            threadLocal.set(sqlSession);

        }
        return sqlSession;
    }

    /**
     * 关闭session
     */

    public static void closeSqlSession() {
        SqlSession sqlSession = threadLocal.get();
        if (sqlSession != null) {
            // 关闭session
            sqlSession.close();
            // 移除session,供GC回收,不然多次访问数据库后会变慢
            threadLocal.remove();

        }
    }

}

2.映射配置

<?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">

<!-- namespace随便起名字 -->
<mapper namespace="studentNamespace">
          <!--  type="com.coffee.mybatis01.entity.Student"名字太长,用别名在mybatis配置文件配置
              id属性用来标记resultmap,如果实体类中的属性和表的字段不一致,用id
              如果都一致,可选
           -->
     <resultMap type="student" id="student">
          <!-- 主键映射 -->
          <id property="id" column="id" />
          <!-- 其他属性映射 -->
          <result property="name" column="name"/>
          <result property="sal" column="sal"/>
     </resultMap>

 <!--
      StudentDao里面的add方法,就是插入方法名称(理论上随便起,方便理解就用一样的名字)
      parameterType方法的参数的类型,写全路径
       -->
       <!-- 无参插入( parameterType="com.coffee.mybatis01.entity.Student"省略) -->
 <insert id="add1" >
      <!-- 插入的sql语句 -->
      insert into students values(1,'张三',7000)
 </insert>

 <!-- 带参插入 -->
 <insert id="add2"  parameterType="student">
      <!-- 插入的sql语句 #{id}==student.getId(),是占位符的意思,hibernate是:= -->
      insert into students values(#{id},#{name},#{sal})
 </insert>

 <!-- 修改值 -->
 <update id="update" parameterType="student">
      update students set name=#{name},sal=#{sal} where id=#{id}
 </update>

 <!-- 查询所有
      resultType返回的是集合,但是我就是要遍历出来student,所以只写student类型
  -->
 <select id="findAll" resultType="student">
      select * from students
 </select>

 <!-- 根据id查询
      resultMap映射resultMap里的id,代表返回值类型,根据id的类型进行返回值判断,resultType比较精确,resultMap是通用的
 -->
 <select id="findById" parameterType="int" resultMap="student">
      select * from students where id=#{id}
 </select>

 <!-- 删除数据 -->
 <delete id="delete" parameterType="int">
      delete from students where id=#{id}
 </delete>

 <!-- ###分页操作 -->
 <!-- 无条件分页 -->
 <select id="findPage" resultMap="student">
  select * from students where id between #{start} and #{end}
 </select>

 <!-- 动态sql查询 -->
 <select id="dynaSelect" parameterType="map" resultMap="student">
      select * from students
          <where>
               <!-- kid是map的Key键,test自动判断key值 -->
               <if test="pid!=null">
                    and id=#{pid}
               </if>
               <if test="pname!=null">
                    and name=#{pname}
               </if>
               <if test="psal!=null">
                    and sal=#{psal}
               </if>

          </where>

 </select>

 <!-- 动态sql update更新
      name=#{name},不要忘了逗号','
      -->
 <update id="dynaUpdate" parameterType="student">
      update students
          <set>
               <if test="name!=null">
                    name=#{name},
               </if>
               <if test="sal!=null">
                    sal=#{sal}
               </if>
          </set>
               where id=#{id}
 </update>

 <!-- 动态sql删除多个#迭代数组 -->
 <delete id="dynaDelete">
      <!-- 删除多个需要遍历数组(这里是数组的遍历array)
            完整的sql是: delete from students where id in (1,3,5)
           collection遍历的类型:array/list
           open开头  close结尾
           item遍历的名称,可以任意写,不需要和dao的一致
           separator分隔符,分割数组的内容
            #{ids}和item的一致
      -->

      delete from students where id in
      <foreach collection="array" open="(" close=")" separator=","  item="ids">
           #{ids}
      </foreach>

 </delete>

 <!-- 动态sql删除多个,迭代list -->
 <delete id="dynaDeleteList">
      delete from students where id in
          <foreach collection="list" open="(" close=")" item="list" separator=",">
               #{list}
          </foreach>
 </delete>

 <!-- ####  动态插入对象 #######-->
 <!--
      insert into students (id,name,value) values (1,"张三",5000.0)
  -->
<!--      <sql id="key">

          <if test="id!=null">id,</if>
          <if test="name!=null">name,</if>
          <if test="sal!=null">sal</if>

 </sql>
 <sql id="value">
      trim标签可以去掉,同时把#{sal},的逗号去掉
      <trim suffixOverrides=",">
          <if test="id!=null">#{id},</if>
          <if test="name!=null">#{name},</if>
          <if test="sal!=null">#{sal},</if>
      </trim>
 </sql>

 <insert id="dynaInsert">
      insert into students (<include refid="key"></include>)
          values(<include refid="value"></include>)
 </insert> -->
 <!-- 效果同上,都可以插入 -->
 <insert id="dynaInsert">
      insert into students (id,name,sal)
          values(#{id},#{name},#{sal})
 </insert>
</mapper>

3.dao调用

package com.coffee.mybatis01.dao;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import utils.MybatisUtil;

import com.coffee.mybatis01.entity.Student;

/**
 * 数据访问层
 * @author wangan
 *
 */
public class StudentDao {

    /**
     * 添加学生--无参
     * @param student
     */
    public void add1() throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        sqlSession.insert("studentNamespace.add1");

        try {
            sqlSession.commit();

        } catch (Exception e) {
            // 回滚操作
            sqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            MybatisUtil.closeSqlSession();
        }

    }

    /**
     * 添加学生--有参
     * @param student
     */
    public void add2(Student student) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        // 插入对象,指定映射空间名称,和<insert>标签的id

        try {
            sqlSession.insert("studentNamespace.add2", student);

        } catch (Exception e) {
            sqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            sqlSession.commit();
            MybatisUtil.closeSqlSession();
        }
    }

    /**
     * 修改学生
     * @param student
     */

    public void update(Student student) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        try {
            sqlSession.update("studentNamespace.update", student);
        } catch (Exception e) {
            sqlSession.rollback();

        } finally {
            sqlSession.commit();
            MybatisUtil.closeSqlSession();
        }
    }

    /**
     * 查询所有学生
     * @param student
     */

    public List<Student> findAll() throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        List<Student> studentList = new ArrayList<Student>();
        try {
            studentList = sqlSession.selectList("studentNamespace.findAll");
        } catch (Exception e) {
            sqlSession.rollback();

        } finally {
            sqlSession.commit();
            MybatisUtil.closeSqlSession();
        }

        return studentList;
    }

    /**
     * 根据id查询学生
     * @param student
     */

    public Student findById(int id) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        Student student = new Student();
        try {
            student = sqlSession.selectOne("studentNamespace.findById", id);
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();

        } finally {
            MybatisUtil.closeSqlSession();
        }
        return student;
    }

    /**
     * 删除学生
     * @param student
     */

    public void delete(int id) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        try {
            sqlSession.delete("studentNamespace.delete", id);
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();

        } finally {
            MybatisUtil.closeSqlSession();
        }
    }

    /**
     * 分页查询--无条件
     */

    public List<Student> findPage(int start, int end) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        List<Student> students = new ArrayList<Student>();
        try {
            Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("start", start);
            map.put("end", end);

            students = sqlSession.selectList("studentNamespace.findPage", map);
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();

        } finally {
            MybatisUtil.closeSqlSession();
        }
        return students;
    }

    /**
     * 动态sql查询--参数使用包装类型进行条件判断时如果是null代表不限,不确定,任意
     */
    public List<Student> dynaSelect(Integer id, String name, Double sal)
            throws Exception {

        SqlSession sqlSession = MybatisUtil.getSqlSession();
        List<Student> list = new ArrayList<Student>();
        try {
            Map<String, Object> map = new LinkedHashMap<String, Object>();

            map.put("pid", id);
            map.put("pname", name);
            map.put("psal", sal);

            list = sqlSession.selectList("studentNamespace.dynaSelect", map);
        } catch (Exception e) {
            sqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            MybatisUtil.closeSqlSession();
        }
        return list;
    }

    /**
     * 动态sql更新
     */
    public void dynaUpdate(Student student) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        try {
            sqlSession.update("studentNamespace.dynaUpdate", student);
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {
            sqlSession.commit();
            MybatisUtil.closeSqlSession();
        }

    }

    /**
     * 动态sql迭代数组--根据id删除多个
     */
    public void dynaDelete(int... ids) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        try {
            sqlSession.delete("studentNamespace.dynaDelete", ids);
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {
            sqlSession.commit();
            MybatisUtil.closeSqlSession();
        }

    }

    /**
     * 动态sql迭代list集合--根据id删除多个
     */
    public void dynaDeleteList(List<Integer> list) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        try {
            sqlSession.delete("studentNamespace.dynaDeleteList", list);
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {
            sqlSession.commit();
            MybatisUtil.closeSqlSession();
        }

    }

    /**
     * 动态sql插入对象
     */
    public void dynaInsert(Student student) throws Exception {
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        try {
            sqlSession.insert("studentNamespace.dynaInsert", student);
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {
            sqlSession.commit();
            MybatisUtil.closeSqlSession();
        }

    }

}

整合之注册功能

1.spring.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans

  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="

   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop.xsd
  http://www.springframework.org/schema/tx
  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  http://www.springframework.org/schema/mvc
  http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

  ">

  <!-- 1. 配置c3p0连接池 -->
  <bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
      <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
      <property name="user" value="wangan"/>
      <property name="password" value="666"/>
  </bean>

  <!-- 2. 配置sqlsession代替原生mybatisUtil工具类 -->
  <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
      <!-- 加载配置文件mybatis.xml -->
      <property name="configLocation" value="classpath:mybatis.xml"/>
      <!-- 引入数据资源 -->
      <property name="dataSource" ref="comboPooledDataSource"/>
  </bean>

  <!-- 3. mybatis事务管理器,底层用的是jdbc -->
  <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <!-- 引入数据源 -->
      <property name="dataSource" ref="comboPooledDataSource"/>
  </bean>

  <!-- 4. 配置事物通知,如何管理事物 -->
  <tx:advice id="tx" transaction-manager="dataSourceTransactionManager">
      <tx:attributes>
          <!-- REQUIRED默认,在有事物情况下执行,没有事物就创建新的事物
               propagation="REQUIRED" 默认
               read-only="false"  默认
           -->
          <tx:method name="*" propagation="REQUIRED" read-only="false"/>
      </tx:attributes>
  </tx:advice>

  <!-- 5.配置事物切面aop,拦截哪些方法 -->
  <aop:config>
      <aop:pointcut expression="execution(* com.coffee.dao.*.*(..))" id="pointcut"/>
      <aop:advisor advice-ref="tx" pointcut-ref="pointcut"/>
  </aop:config>


  <!-- 注册dao -->
  <bean id="studentDao" class="com.coffee.dao.StudentDao">
      <property name="sqlSessionFactory" ref="sqlSessionFactoryBean"/>
  </bean>
  <!-- 注册service -->
  <bean name="studentService" class="com.coffee.service.StudentService">
      <property name="studentDao" ref="studentDao"></property>
  </bean>

  <!-- 注册action(注解),里面有service,service加了注解,扫描 -->
  <context:component-scan base-package="com.coffee"/>


  <!-- 通知springioc注解作用 -->
  <context:annotation-config />



  <!-- 视图解析器 -->
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/jsp/"></property>
      <property name="suffix" value=".jsp"></property>
  </bean>


</beans>

3.dao

package com.coffee.dao;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.coffee.entity.Student;

/**
 * 数据访问--StudentDao
 * @author wangan
 *
 */
public class StudentDao {

    // 注入sqlsession工厂
    private SqlSessionFactory sqlSessionFactory;

    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    /**
     * 添加学生
     * @param student
     * @throws Exception
     */
    public void add(Student student) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.insert("studentNamespace.add", student);
        sqlSession.close();

    }
}

3.service

package com.coffee.service;

import com.coffee.dao.StudentDao;
import com.coffee.entity.Student;

/**
 * 数据访问
 * @author wangan
 *
 */
public class StudentService {

    private StudentDao studentDao;

    public void setStudentDao(StudentDao studentDao) {
        this.studentDao = studentDao;
    }

    public void register(Student student) throws Exception {
        try {
            studentDao.add(student);
        } catch (Exception e) {

            e.printStackTrace();
        }

    }
}

4.Action

package com.coffee.action;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.coffee.entity.Student;
import com.coffee.service.StudentService;

/**
 * action
 * @author wangan
 *
 */
@Controller
@RequestMapping(value = "/student")
public class StudentAction {

    private StudentService studentService;

    @Resource(name = "studentService")
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }

    /**
     * 注册学生
     * @param student
     * @return
     */
    @RequestMapping(value = "/register")
    public String registerStudent(Student student) {
        try {
            studentService.register(student);
        } catch (Exception e) {

            e.printStackTrace();
        }
        return "success";
    }

}

5.test

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.coffee.dao.StudentDao;
import com.coffee.entity.Student;

/**
 * 测试整合
 * @author wangan
 *
 */
public class TestSpring_mybatis {

    public static void main(String[] args) {

        Student student = new Student(20, "王林", 8000d);

        ApplicationContext ac = new ClassPathXmlApplicationContext(
                new String[] { "spring.xml" });
        StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
        try {
            studentDao.add(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

1.web.xml

数据回显

 /**
  * 3. 修改员工-进入修改页面(list.jsp里面的修改 链接跳转到这里)
  * struts2的保存修改数据的方式就是模型驱动,先把旧的数据移除,新的压进栈
  */
 public String viewUpdate() {// 更新一条记录的关键步骤
      // 1.获取主键
      int id = employee.getEmployeeId();
      // 2.根据员工的主键查询,此时已经有部门信息(lazy=false)
      Employee employee = employeeService.findById(id);
      // 3. 查询所有的部门信息
      List<Dept> listDept = deptService.getAll();

      // 4.数据回显
      // 获取valueStack对象
      ValueStack valueStack = ActionContext.getContext().getValueStack();
      // 移除栈顶元素(旧的)
      valueStack.pop();
      // 入栈,即将更新的值
      valueStack.push(employee);
      request.put("listDept", listDept);
      return "edit";

 }

下拉列表

 <td>
     <!-- name="deptId"随便取,代表下拉列表名字 -->
     <s:select list="#request.listDept" listKey="deptId" listValue="deptName" name="deptid" headerKey="-1" headerValue="请选择" value="-1"></s:select>
 </td>

做注册的时候员工的信息联系到另外一张表部门表,下拉菜单选择部门的时候这个deptid顺带传过去

提交到注册action

// 封装部门id,下拉列表里面的name=“deptid”的值
     private int deptid;

     public void setDeptid(int deptid) {
          this.deptid = deptid;
     }

     public int getDeptid() {
          return deptid;
     }


//注册
public String save() {
          // 先根据部门主键查询
          Dept dept = deptService.findById(deptid);
          // 部门设置到员工对象中
          employee.setDept(dept);
          // 保存员工
          employeeService.save(employee);

          return "listAction";// 重定向到Action
     }

mybatis工作流程:

1)通过Reader对象读取src目录下面的mybatis.xml配置文件(可自定义路径)
2)通过SqlSessionBuilder对象创建SqlSessionFactory对象
3)从当前线程中获取SqlSession对象
4)事物开始,在mybatis中默认
5)通过SqlSession对象读取StudentMapper.xml映射文件中的操作编号,从而读取sql语句
6)事物必须提交
7)关闭SqlSession对象.并且分开当前线程与SqlSession对象,让GC尽早回收

mybatis01

mybatis

批量插入数据–list集合


INSERT INTO BUY_ORDER_DETAIL (BOD_ID, GOODS_ID, GOODS_NAME,
GOODS_UNIT, GOODS_TYPE, GOODS_COLOR,
BOD_AMOUNT, BOD_BUY_PRICE, BOD_TOTAL_PRICE,
BO_ID, BOD_IMEI_LIST)

SELECT
#{item.bodId,jdbcType=VARCHAR}, #{item.goodsId,jdbcType=VARCHAR},
#{item.goodsName,jdbcType=VARCHAR},#{item.goodsUnit,jdbcType=VARCHAR},
#{item.goodsType,jdbcType=VARCHAR}, #{item.goodsColor,jdbcType=VARCHAR},
#{item.bodAmount,jdbcType=DECIMAL}, #{item.bodBuyPrice,jdbcType=DECIMAL},
#{item.bodTotalPrice,jdbcType=DECIMAL}, #{item.boId,jdbcType=VARCHAR},
#{item.bodImeiList,jdbcType=CLOB}
FROM DUAL



SELECT * FROM (
SELECT ROWNUM RN,GO.* FROM
(SELECT * FROM GOODS

AND GOODS_NAME LIKE #{paramEntity.goodsName}

ORDER BY GOODS_ID)GO
WHERE ROWNUM <= #{start}+#{rows})
WHERE RN > #{start}

错误例2:将整个sql语句用<\![CDATA[ ]]>标记来避免冲突,在一般情况下都是可行的,
是由于该sql配置中有动态语句(where部分),将导致系统无法识别动态判断部分,
导致整个sql语句非法。

\
<\![CDATA[ select id from tableA a,tableB b \ \
a.act_time >= #startDate# and a.act_time <= #endDate# and a.id = b.id
\ ]]> \ 正确做法:缩小范围,只对有字符冲突部分进行合法性调整。
\ select id
from tableA a, tableB b \ \
a.act_time >= #startDate# <\![CDATA[ and a.act_time <= #endDate# ]]> and a.id = b.id
<\/isNotNull> <\/dynamic> <\/select>

ibatis中应该经常见到

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringMyBatis整合是非常常见且流行的,可以通过以下步骤进行整合: 1. 添加依赖:在项目的构建文件(如pom.xml)中添加SpringMyBatis的相关依赖。确保版本兼容性。 2. 配置数据源:在Spring的配置文件(如application.xml)中配置数据源,例如使用连接池(如C3P0、HikariCP)或者直接配置数据库连接。同时,配置MyBatis的一些属性,如Mapper扫描路径等。 3. 配置SessionFactoryBean:使用Spring提供的org.mybatis.spring.SqlSessionFactoryBean配置MyBatis的SqlSessionFactory。可以设置数据源、类型别名、Mapper扫描路径等。 4. 配置MapperScannerConfigurer:使用Spring提供的org.mybatis.spring.mapper.MapperScannerConfigurer配置MyBatis的Mapper扫描路径。可以通过配置basePackage属性设置扫描路径。 5. 编写Mapper接口和Mapper映射文件:创建Mapper接口,并在接口中定义需要的数据库操作方法。然后编写对应的Mapper映射文件,配置SQL语句和结果映射。 6. 注入Mapper接口:在需要使用Mapper接口的地方(如Service层),通过@Autowired或配置文件注入该接口,然后即可调用接口中定义的方法。 7. 开启事务支持:在Service层或需要事务管理的地方,使用Spring提供的@Transactional注解或配置文件声明事务。 以上是简要的整合步骤,具体配置和代码实现可能因项目需求和环境而有所不同。整合完成后,即可在Spring项目中使用MyBatis进行数据库操作,并利用Spring的特性实现更加灵活和便捷的开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值