什麼是框架 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>
以上兩種辦法均可以解決上述的問題。。。。