发表于: 2018-04-03 12:08:51

1 833



day6




今天完成的事情:


1. 关于log4j,property文件一定要放在src下,我放在了二级目录下然后用Spring核心配置文件加载发现没有打印日志,说明该文件是log4j自己默认在一级目录下读取的,或许在内部有配置文件可以配置该路径。

二级目录下用Spring的applicationContext读取没用,

要放在一级目录下


2. 在这里,我用的是classpath,但是看别人有用classpath*的,关于两者的区别是:

classpath:只会到你的class路径中查找找文件;

classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找.

就是说classpath*会在所有的classpath里遍历查找,详见:https://blog.csdn.net/u011679955/article/details/52801223


3. MyBatis的一大亮点就是可以不用DAO的实现类。如果没有实现类,Spring如何为Service注入DAO的实例呢?MyBatis-Spring提供了一个MapperFactoryBean,可以将数据映射接口转为Spring Bean。

<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">

    <property name="mapperInterface" value="dao.UserMapper"/>

    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>

</bean>

如果数据映射接口很多的话,需要在Spring的配置文件中对数据映射接口做配置,相应的配置项会很多了。为了简化配置,在MyBatis-Spring中提供了一个转换器MapperScannerConfigurer,它将扫描basePackage所指定的包下的所有接口类(包括子类),如果它们在SQL映射文件中定义过,则将它们动态定义为一个Spring Bean,这样,我们在Service中就可以直接注入映射接口的bean。

以下是注入在测试类中注入接口实例,其实就是上个日报里的代码节选

//@Autowired注解,从容器中找到该对象自动注入。
@Autowired
private SqlSessionFactory sqlSessionFactory;
@Autowired
private PersonDaoMapper persondao;
@Test  //
public void testAdd() throws Exception{
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="a.b.mapperdao"/>
</bean>

扩展阅读:

使用MapperScannerConfigurer简化MyBatis配置:

https://blog.csdn.net/u011318776/article/details/52819241

关于@Autowired :

https://www.cnblogs.com/caoyc/p/5626365.html

Mybatis实现Mapper动态代理方式:https://blog.csdn.net/lu930124/article/details/50991899 

mybatis源码学习--spring+mybatis注解方式为什么mybatis的dao接口不需要实现类:

 https://blog.csdn.net/mingtian625/article/details/47684271


4.(重点)

 spring-mybatis 之SqlSessionFactoryBean https://blog.csdn.net/liuxiao723846/article/details/52424802(建议精读)

 以上连接回答了我很多问题,比如以下代码

//@Autowired注解,从容器中找到该对象自动注入。
//@Autowired
//private SqlSessionFactory sqlSessionFactory;
@Autowired
private PersonDaoMapper persondao;
@Test  //
public void testAdd() throws Exception{

Person person = new Person();
person.setNAME("霍元刚");
person.setGender("");
person.setAge("49");
persondao.add(person);
System.out.println("执行了ADD方法....");
}

 我把sqlSessionFactory注释掉,还可以正常运行,那么谁给我的sqlSessionFactory,而且我也没有创建sqlSession,

 既没有在Spring中配置sqlSession也没有在类中声明创建,甚至后面的提交事务事务回滚都没有操作,而这一切都是因为配置了

 MapperScannerConfigurer,它会自动扫描自动创建代理类。

在 MyBatis 中,使用 SqlSessionFactoryBuilder创建SqlSessionFactory ,进而来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射语句,提交或回滚连接,最后,当不再需要它的时候, 你可以关闭 session。 

Mybatis社区自己开发了一个Mybatis-Spring用来满足Mybatis用户整合Spring的需求。

使用 MyBatis-Spring 之后, 会使用SqlSessionFactoryBean来代替SqlSessionFactoryBuilder创建SqlSessionFactory,然后可以在Spring中配置sqlSession。

SqlSessionTemplate:

Mybatis-Spring提供了一种直接使用SqlSession的方式(一个实现了SqlSession接口的SqlSessionTemplate实现类)

1.它是线程安全的,可以被多个Dao同时使用;

2.它跟Spring的事务进行了关联,确保当前被使用的SqlSession是一个已经和Spring的事务进行绑定了的,而且它还可以自己管理Session的提交和关闭。

<context:annotation-config/>
<!-- 扫描servicedao组件 -->
<context:component-scanbase-packagecontext:component-scanbase-package="cn.edu.nuc" />
<!-- 分解配置 jdbc.properites -->
<context:property-placeholder location="classpath:jdbc.properties" />

<!-- 数据源c3p0 -->
<bean id="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl"value="${jdbc.url}" />
<property name="user"value="${jdbc.username}" />
<property name="password"value="${jdbc.password}" />
</bean>

<!--配置sqlSessionFactory-->
<bean id="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource"  ref="dataSource" />
<property name="configLocation" value="classpath:mybatis/configuration.xml"/>
<property name="mapperLocations" value="classpath*:cn/edu/nuc/map/*.xml"/>
</bean>

<bean id="sqlSession"class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0"ref="sqlSessionFactory" />
</bean>


5.通过注解实现了一遍增删查改

public interface PersonDao4 {

@Insert("insert into table1(NAME,gender,age) values(#{NAME},#{gender},#{age})")
public void add(Person person);

//注意这里只有一个参数,则#{}中的标识符可以任意取
  @Select("select id,NAME,gender,age from table1 where id = #{id}")
public Person findById(int id) ;

@Select("select id,NAME,gender,age from table1")
public List<Person> findAll();

@Update("update table1 set name=#{NAME},gender=#{gender},age=#{age} where id=#{id}")
public void update(Person person) ;

@Delete("delete from table1 where id = #{id}")
public void delete(Person person);

@Select("select id,NAME,gender,age from table1 where NAME = #{NAME}")
void findByName(String name) ;

这样把mapper.xml注释掉也可以运行了。然后优化了工具类

public  class MybatisUtil {

private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
private static SqlSessionFactory sqlSessionFactory;

/**
   * 静态块,类加载时即执行以下代码
   * 优点:最快加载,而且只加载一次
   */

  //加载位于src/mybatis.xml配置文件

static{

  try {
    Reader reader = Resources.getResourceAsReader("mybatis/mybatis-config.xml");
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

     //由于使用了注解,所以在主配置文件没有mapper,需要在代码里显示注册该mapper接口
   sqlSessionFactory.getConfiguration().addMapper(PersonDao4.class);

  } catch (IOException e) {
    e.printStackTrace();
throw new RuntimeException(e);
 }
  }
/**
   * 禁止未接通过new方法创建
   * 因为上面的静态代码块在类每new
一次时也会加载,这样会很多次加载耗费性能
   */
  private MybatisUtil(){}


//获取SqlSession
  public static SqlSession getsqlSession(){
//从当前线程中获取Sqlsession对象
     SqlSession sqlSession = threadLocal.get();
//如果sqlSession对象为空
     if(sqlSession==null){
//sqlSessionFactory非空的情况下,获取sqlSession对象
        sqlSession = sqlSessionFactory.openSession();
//sqlSession对象与当前线程绑定在一起
        threadLocal.set(sqlSession);

     }
return sqlSession;
  }

//关闭SqlSession与当前线程分开
  public static void closesqlSession(){
// 从当前线程中获取Sqlsession对象
     SqlSession sqlSession = threadLocal.get();
// 如果sqlSession对象非空
     if (sqlSession != null) {
//关闭SqlSession对象
        sqlSession.close();
//分开当前线程与sqlsession对象的关系,为了让GC尽早回收
        threadLocal.remove();
//或者threadLocal.set(null);
       
     }
  }

public static void main(String[] args) {
     Connection conn = MybatisUtil.getsqlSession().getConnection();
     System.out.println(conn!=null?"连接成功":"连接失败");
  }
}

直接调用工具栏实现增删查改,这里只展示增

public class testPerson4 {

private static PersonDao4 persondao;

@Test  //
  public void testAdd() throws Exception{
SqlSession sqlSession = null;

Person person = new Person();
person.setNAME("张无忌");
person.setGender("");
person.setAge("21");

try {
sqlSession = MybatisUtil.getsqlSession();
persondao = sqlSession.getMapper(PersonDao4.class);
persondao.add(person);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
//事务回滚
        sqlSession.rollback();
throw e;
} finally{
MybatisUtil.closesqlSession();
}
}

单步调试观察变量赋值情况



小课堂(我自己的小课堂,不是咱修真院的):


(1) 异常捕获 try catch finally

try { //执行的代码,其中可能有异常。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容 } 

catch { //除非try里面执行代码发生了异常,否则这里的代码不会执行 } 

finally { //不管什么情况都会执行,包括try catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally }


(2)static关键字 :https://www.cnblogs.com/dotgua/p/6354151.htmlutm_source=itdadao&utm_medium=referral(重要级链接)


(3)连接池

    最原始的数据库连接就是我们打开一个连接,使用后再关闭该连接释放资源。频繁的新建、打开、关闭连接对jvm和数据库都有一定的资源负荷,尤其是应用压力比较大的时候,占用过多的资源容易产生性能问题,所以引入数据库连接池。

    数据库连接池的基本思想就是为数据库连接建立一个"缓冲池",预先在缓冲池中放一定数量的连接,当需要建立数据库连接时,只需从"缓冲池"中取一个,使用完毕之后在放回去。



明天计划的事情:


本来要部署云端数据库的,但是上级有要求我手打一遍Spring+Mybatis,老夫只好再来一遍了。然后再琢磨下如何部署数据库到云服务器。


遇到的问题:


一些代码本来好好的突然报错,后来发现是因为我Idea和Myeclipse同时打开了这个project,大概两个软件有冲突吧 。


收获:

 

数据库连接池;Static关键字;还有Spring提供的对mybatis支持的包,大大简化了开发。






返回列表 返回列表
评论

    分享到