什么是框架 java
在的J2EE开发中,常常会提到“框架”这个词汇,例如Spring,Struts,Webx等等都称之为J2EE开发框架。那么,什么是框架呢? mysql
框架的英文为Framework,带有骨骼,支架的含义。 算法
在软件工程中,框架被定义为整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另外一种定义认为,框架是可被应用开发者定制的应用骨架。spring
一个框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协做构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协做的方法,它为构件复用提供了上下文(Context)关系。 sql
框架是实现了某应用领域通用功能的底层服务。使用这种框架的编程人员能够在一个通用功能已经实现的基础上开始具体的系统开发。框架提供了全部应用指望的默认行为的类集合。具体的应用经过重写子类或组装对象来支持应用专用的行为。 数据库
通俗的说,框架是完成是某种应用的半成品,提供了一些经常使用的工具类和一些基础通用化的组件,能够供开发人员在此基础上,更便捷的完成各自特有的系统。 express
Spring是一个综合型框架,致力于J2EE应用的各层的解决方案,而不是仅仅专一于某一层的方案。能够说Spring能够做为应用开发的“一站式”选择,并贯穿表现层、业务层及持久层。然而,Spring并不想取代那些已有的框架,它能够与其余框架无缝地整合。编程
考虑到面向的领域,以及实现编码实现,咱们能够将将框架至少分为三类。安全
第一类是基础类库,主要包含多数项目所须要的类库。(开发人员将其做为一个类库使用,能够简化一些经常使用的算法逻辑。) session
第二类是基础框架,该框架应该整合或者实现J2EE开发所须要的经常使用功能。(此框架能够为各种WEB项目开发提供基础支持。)
第三类是平台框架,针对于某种特定领域,实现特定领域所须要的经常使用功能。(这个框架须要实现具体领域的业务的逻辑。而且应该支持各种扩展)
为何须要整合呢?
使用spring ,主要是使用它的ioc(能够理解成管理bean的一个容器) ,aop(面向切面编程:持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等) ,jdbcTemplate(封装操做数据库,不用再本身创建关闭链接了,挺方便的。)
固然还有一部分是工做须要, spring的IOC能够下降对象的耦合度,方便用junit作自动化测试.
以上的部分只是本身摘抄的我的理解。
接下来开始真正进入代码的世界,咱们来实现一个添加图书和查询图书信息的功能。使用Spring和Hibernate整合
建立实体类:
package cn.books.beans; /** * Created by accp on 2017/3/30. */ public class Book { private Integer id; private String name; private String price; public Book() { } public Book(String name, String price) { this.name = name; this.price = price; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } }
小配置:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.books.beans"> <class name="Book" table="Book"> <id name="id"><generator class="native"></generator></id> <property name="name"/> <property name="price"/> </class> </hibernate-mapping>
dao:
package cn.books.dao; import cn.books.beans.Book; /** * Created by accp on 2017/3/30. */ public interface BookDao { int add(Book book); }
dao层的实现(implements):
package cn.books.dao.impl; import cn.books.beans.Book; import cn.books.dao.BookDao; import org.hibernate.SessionFactory; import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; /** * Created by accp on 2017/3/30. */ public class BookDaoImpl implements BookDao { private SessionFactory sessionFactory; @Transactional public int add(Book book) { Serializable count = sessionFactory.getCurrentSession().save(book); return (Integer) count; } public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } }
biz层(业务逻辑):
package cn.books.biz; import cn.books.beans.Book; /** * Created by accp on 2017/3/30. */ public interface BookBiz { int add(Book book); }
biz的实现层:
package cn.books.biz.impl; import cn.books.beans.Book; import cn.books.biz.BookBiz; import cn.books.dao.BookDao; /** * Created by accp on 2017/3/30. */ public class BookBizImpl implements BookBiz{ private BookDao dao; public int add(Book book) { return dao.add(book); } public BookDao getDao() { return dao; } public void setDao(BookDao dao) { this.dao = dao; } }
这些类建立完成了,接下咱们就改配置applicationContext.xml了。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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.xsd "> <!--注入jdbc.properties--> <context:property-placeholder location="classpath:jdbcmysql.properties"></context:property-placeholder> <!--数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--sessionFactory配置--> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <!--方言--> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <!--获取当前线程中的session--> <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</prop> </props> </property> <!--关联小配置--> <property name="mappingDirectoryLocations" value="classpath:cn/books/beans"></property> </bean> <!--dao--> <bean id="bookDao" class="cn.books.dao.impl.BookDaoImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!--biz--> <bean id="bookBiz" class="cn.books.biz.impl.BookBizImpl"> <property name="dao" ref="bookDao"></property> </bean> <!--事务管理器--> <bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven> </beans>
支持咱们项目的一系列的jar包节点
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.3</version> </dependency> <!--jta的jar包--> <dependency> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> <version>1.1</version> </dependency> <!--mysql数据库驱动--> <dependency> <groupId>org.wisdom-framework</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34_1</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.0.6.Final</version> </dependency> <!--以上是HIbernate的jar包配置--> <!--下面是Spring相关的jar包配置--> <!--c3p0--> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <!--AOP的相关jar--> <dependency> <groupId> org.aspectj</groupId > <artifactId> aspectjweaver</artifactId > <version> 1.8.7</version > </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.0.RELEASE</version> </dependency> <!--Spring-ORM--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version> 4.2.2.RELEASE</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build>
前期准备工做完成,最后进入测试阶段:
package cn.books.test; import cn.books.beans.Book; import cn.books.biz.BookBiz; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by accp on 2017/3/29. */ public class FirstTest { @Test public void findTwo(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContextbase.xml"); BookBiz proxy=(BookBiz) ctx.getBean("bookBiz"); int count = proxy.add(new Book("天空之城", "65")); System.out.println(count); } }
结果:
DEBUG SQL:92 - insert into Book (name, price) values (?, ?) Hibernate: insert into Book (name, price) values (?, ?)
DEBUG EntityPrinter:109 - cn.books.beans.Book{id=7, price=65, name=天空之城}
7
数据库数据:
使用查询功能:
添加方法:List<Book> selectAll();--------------->dao
private SessionFactory sessionFacctory;
@Transcational
public List<Book> selectAll() {
List<Book> list=sessionFactory.getCurrentSession().createCriteria(Book.class).list();
return list;
}
-------------------->dao.impl
List<Book> selectAll();--------------->biz
private BookDao dao;
public List<Book> selectAll(){
return dao.selectAll();
}
-------------------->biz.impl
applicationContext.xml配置文件不须要修改和添加,书写测试类便可。
@Test public void findOne(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContextbase.xml"); BookBiz proxy=(BookBiz) ctx.getBean("bookBiz"); List<Book> list = proxy.selectAll(); for (Book item : list) { System.out.println("名称:"+item.getName()+"\t价格:"+item.getPrice()); } }
控制台上的数据显示:
DEBUG SQL:92 - select this_.id as id1_0_0_, this_.name as name2_0_0_, this_.price as price3_0_0_ from Book this_ Hibernate: select this_.id as id1_0_0_, this_.name as name2_0_0_, this_.price as price3_0_0_ from Book this_
16:38:35,068 DEBUG EntityPrinter:102 - Listing entities: 16:38:35,068 DEBUG EntityPrinter:109 - cn.books.beans.Book{id=6, price=65, name=天空} 16:38:35,069 DEBUG EntityPrinter:109 - cn.books.beans.Book{id=5, price=65, name=天空} 16:38:35,069 DEBUG EntityPrinter:109 - cn.books.beans.Book{id=4, price=65, name=天空} 16:38:35,069 DEBUG EntityPrinter:109 - cn.books.beans.Book{id=3, price=65, name=你好吗?天空} 16:38:35,069 DEBUG EntityPrinter:109 - cn.books.beans.Book{id=2, price=45, name=图书第二次} 16:38:35,069 DEBUG EntityPrinter:109 - cn.books.beans.Book{id=1, price=45, name=图书} 16:38:35,069 DEBUG EntityPrinter:109 - cn.books.beans.Book{id=7, price=65, name=天空之城} 16:38:35,072 DEBUG HibernateTransactionManager:680 - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[cn.books.beans.Book#6], EntityKey[cn.books.beans.Book#5], EntityKey[cn.books.beans.Book#4], EntityKey[cn.books.beans.Book#3], EntityKey[cn.books.beans.Book#2], EntityKey[cn.books.beans.Book#1], EntityKey[cn.books.beans.Book#7]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction
名称:图书 价格:45 名称:图书第二次 价格:45 名称:你好吗?天空 价格:65 名称:天空 价格:65 名称:天空 价格:65 名称:天空 价格:65 名称:天空之城 价格:65
在整合Spring和Hibernate时候遇到的问题最多的就是:
Could not obtain transaction-synchronized Session for current thread
提示没法获取当前线程的事务同步session,略微奇怪,这和事务有什么关系..而后百度一下有人说改为用openSession方法就行了,那我又百度了一下这2个方法的区别:
(1)openSession每次打开都是新的Session,因此屡次获取的Session实例是不一样的,而且须要人为的调用close方法进行Session关闭。
(2)getCurrentSession是从当前上下文中获取Session而且会绑定到当前线程,第一次调用时会建立一个Session实例,若是该Session未关闭,后续屡次获取的是同一个Session实例;事务提交或者回滚时会自动关闭Sesison,无需人工关闭。
如今咱们所作的测试都是在控制台上打印输出的,还没涉及到在页面上显示数据,当咱们在页面上得到数据时要在保证在同一个会话中完成,因此当咱们使用openSession()方法时不会出现错误,可是当咱们在当前线程内获取session时会出现上述的错误。。
解决办法:
在dao层的方法上面加上@Transcational注解,在applicationContext.xml中添加上:
<!--事务管理器--> <bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven>
或者换一种别的配置方法:
Aop方法
<!--事务管理器--> <bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>
<tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="select*" isolation="DEFAULT" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="point" expression="execution(* *..biz.*.*(..))"></aop:pointcut> <aop:advisor advice-ref="txAdvice" pointcut-ref="point"></aop:advisor> </aop:config>
以上两种办法均可以解决上述的问题。。。。