发表于: 2018-04-03 12:08:51
1 832
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/>
<!-- 扫描service、dao组件 -->
<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支持的包,大大简化了开发。
评论