Spring与Hibernate整合实现(SH框…
来源:互联网 发布:小额贷款骗局知乎 编辑:程序博客网 时间:2024/06/09 17:43
先放图,本节的工程文件目录结构如下:
以及要导入的额外库文件(记得加上Hibernate库和SpringFramework的库):
其中:
aopalliance.jar
aspectjweaver-1.7.2.jar
可能需要到网上下载。随便百度个就行,蛮多人分享的。
Spring与Hibernate两边结合在一起之后,Spring对Hibernate的一些启动操作进行了接管。毕竟Spring本身是一个管理类工厂的服务,而许多程序、应用的初始化操作,可以交给Spring来完成。
于是,Hibernate里面的数据库地址、用户名、密码和操作参数等,统统交给Spring来接管了,我们无需担心。于是Hibernate.cfg.xml文件变得异常简洁。记得在上一节讲解Hibernate的时候,启动一个服务要写相当多的启动代码:
然后才是业务代码(也就是功能代码):
其实Hibernate只需要启动一次,然后整个项目都用一个或者两个实例就好(根据线程的负载和锁的情况,别造成这个用了Hibernate,那个急着用又用不上又不能自己生成一个实例来用)。所以具体怎么管理,怎么生成,或者什么时候用这些类的实例(Configuration、StandardServiceRegistryBuilder、ServiceRegistry、SessionFactory等等 )就交给Spring框架来决定吧。我们看到,其实最主要的功能,集中在session处。如何保存、如何从数据库获取一行,都要靠session来执行。那么其实把冗余的初始化功能分离后,剩下的东西,写进一个功能模块里面,就成了DAO(DataAccess Object数据访问对象)。我们来看这么一段代码:
文件BookDao.java
public interface BookDao{ public String findBookById(int id); public void saveBook(Book book);
}
可以看到,其实DAO类(或接口)就是一个封装了数据库操作的类(或接口)。DAO意味着封装了非常非常具体的数据库操作后,直接得到的服务。它可以是查询某个id得到这个id下的书名字符串,也可以是新建并保存一个书本条目。我们看到这个类使用了POJO类Book,Book的定义会在后面给出。具体怎么塞到数据库里面的,得由这个类的实现(implements)来进行:
文件BookDaoImpl.java
package dao_service;
@Autowired private SessionFactorysessionFactory; //获取和当前线程绑定的Session private Session getSession(){ returnsessionFactory.getCurrentSession(); } @Override public StringfindBookById(int id){ //String hql="SELECT bookNamefrom Book where id=?";//直接使用id=?会有问题 //Queryquery=getSession().createQuery(hql).setInteger(0, id); Stringhql="SELECT bookName from Book where id=?0";//使用JPA方式,改为?0 //即可用setParameter设置参数 Queryquery=getSession().createQuery(hql); query.setParameter("0", id); Stringstr= query.uniqueResult().toString(); returnstr; } @Override public voidsaveBook(Book book){ getSession().save(book); }
importorg.hibernate.Query;
importorg.hibernate.Session;
importorg.hibernate.SessionFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Repository;
importtable.book.Book;
@Repository
public class BookDaoImplimplements BookDao{
}
从这个BookDaoImpl类实现,我们可以看到内置了一个SessionFactory。细心的同学会发现,有这个private类,却没有具体的实现,也没有setSessionFactory方法来设置它。它在saveBook()方法使用的时候不会是个空指针吗?
奥妙就在这里,其实这个类内实例的导入,是由Spring来完成的。Spring跟Hibernate结合以后,提供了一系列自动化方法,比如可以自动搜索dao_service文件夹(也就是BookDao.java和BookDaoImpl.java存放的文件夹)下的类,根据关键词过滤来判断哪些是类的实现,根据方法名或者内部私有变量的名字,来判断装入何种类的实现(如具体的SessionFactory等等)。
为了验证自动装配这一点,我们给它再套一个壳子,我们新建一个BookService类,里面提供的服务和内容跟BookDao类完全一样:
文件BookService.java
public interfaceBookService{ public String findBookById(int id); public void saveBook(Book book);
}
然后我们建立一个实现,同样是在接口名后面加上Impl:
文件BookServiceImpl.java
package dao_service;
@Autowired private BookDao bookDao; @Override public String findBookById(int id) { returnbookDao.findBookById(id); } @Override public void saveBook(Book book) { bookDao.saveBook(book); }
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importtable.book.Book;
@Service
public class BookServiceImplimplements BookService
{
}
这个壳子啥都没做,仅仅是用了BookDao接口的方法来完成自己的方法。注意,在BookServiceImpl里所使用的不是BookDaoImpl的方法,而是BookDao,说明我们要想使用,必须得有个具体的实现。意味着整个过程必须有人来搞。这个人显然就是Spring。有兴趣的同学可以写一个计数器,看看Spring生成了多少个实例,并且都调用了哪个实例来使用(提示:用静态变量作计数器,则所有实例之间都可以共享了。不懂是否线程安全,为了准确计数,可以考虑加锁)
说了这么多,那么实体类(EntityClass)呢?在这里定义:
文件Book.java
package table.book;
private static final long serialVersionUID =1L; @Id private Integer id; private String bookName; private String isbn; private int price; private int stock;
public Book() { } public Book(Integer id, String bookName, Stringisbn, int price, int stock){ super(); this.id =id; this.bookName = bookName; this.isbn= isbn; this.price= price; this.stock= stock; } public Integer getId(){ return id; } public void setId(Integer id){ this.id = id; } public String getBookName(){ return bookName; } public void setBookName(String bookName){ this.bookName =bookName;} public String getIsbn(){ return isbn; } public void setIsbn(String isbn){ this.isbn = isbn; } public int getPrice(){ return price; } public void setPrice(int price){ this.price = price; } public int getStock(){ return stock; } public void setStock(int stock){ this.stock = stock; }
//importorg.hibernate.annotations.Entity;这个已经过时,用javax里面的entity代替
importjavax.persistence.Entity;
importjavax.persistence.Id;
importjava.io.Serializable;
@Entity
public class Book implementsSerializable {
}
可以看到这个Book实体类里面有5个属性,对应着数据库表中5个列:id、bookname、isbn、price、stock。同理,给这个Book.java配置一个文件给hibernate读取:
文件Book.hbm.xml
<?xmlversion="1.0"?> <classname="table.book.Book"table="BOOK"> <id name="id"type="java.lang.Integer"> <columnname="ID"/> <generatorclass="native"/> </id> <propertyname="bookName"type="java.lang.String"> <columnname="BOOK_NAME"/> </property> <propertyname="isbn"type="java.lang.String"> <columnname="ISBN"/> </property> <propertyname="price"type="int"> <columnname="PRICE"/> </property> <propertyname="stock"type="int"> <columnname="STOCK"/> </property> </class>
<!DOCTYPEhibernate-mapping PUBLIC "-//Hibernate/HibernateMapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-3-15 16:30:05 byHibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
</hibernate-mapping>
接下来我们看看具体hibernate的配置文件:
文件hibernate.cfg.xml
<?xmlversion="1.0"encoding="UTF-8"?> "-//Hibernate/Hibernate Configuration DTD3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 十二月 08, 201612:48:02 下午 org.hibernate.internal.util.xml.DTDEntityResolverresolveEntity WARN: HHH000223:Recognized obsolete hibernate namespacehttp://hibernate.sourceforge.net/. Use namespacehttp://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6Migration Guide! 如果对这个警告心烦的,可以把网址按照警告的要求来改。 <session-factory> <!-- 配置Hibernate的基本属性--> <!-- 1.数据源配置到IOC容器中--> <!--2.关联的.hbm.xml也在IOC容器配置SessionFactory实例--> <!--3.配置Hibernate的基本属性:方言,SQL显示及格式化,生成数据表的策略以及二级缓存--> <propertyname="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <propertyname="hibernate.show_sql">true</property> <propertyname="hbm2ddl.auto">update</property> </session-factory>
<!DOCTYPEhibernate-configuration PUBLIC
<!--
-->
<hibernate-configuration>
</hibernate-configuration>
明显少了很多东西。这些本该在hibernate.cfg.xml中的配置被转移到了Spring配置文件里面了:
文件applicationContext.xml
<?xmlversion="1.0"encoding="UTF-8"?> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.1.xsd"> <!-- http://zghbwjl.blog.163.com/blog/static/120336672201092294943744/ 一看这个错误肯定是少包或者是包冲突,知道原因就找吧,根据这句: java.lang.NoClassDefFoundError:org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException, 可以看出应该是少了aspectjweaver.jar这个jar包,加上就可以了。 --> <!-- context:component-scanbase-package这是拿来扫描beans所在目录的 所以要scan所定义的beans的目录。目前定义的就是DAO一些列bean http://blog.csdn.net/chenweihaoshuai/article/details/8036671 目录不对会报错: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nobean named 'xx' isdefined --> <context:component-scanbase-package="dao_service"></context:component-scan> <beanid="dataSource"class="org.apache.commons.dbcp2.BasicDataSource"destroy-method="close"> <!-- 尝试导入commons-dbcp2-2.1.1.jar包。解决这个BasicDataSource的问题 然后确实要导入相应的pool2包 这里可能是用来接管Hibernate的数据库定义的。账户、密码都不在hibernate.hbm.xml里面定义了 参考资料:http://blog.csdn.net/a105421548/article/details/43016953 密码等定义如下: --> <propertyname="driverClassName"value="com.mysql.jdbc.Driver"/> <!--<propertyname="url"value="jdbc:mysql://localhost/test"/>--> <propertyname="url"value="jdbc:mysql://localhost:3306/student_manager?useSSL=true"/> <propertyname="username"value="root"></property> <propertyname="password"value="passwordOfRoot"></property> </bean> <!-- 常规的hibernate包缺失问题。项目事实的时候,最后SSH都分开,单独测试一下 nested exception isjava.lang.NoClassDefFoundError:javax/persistence/Entity 缺少hibernate-jpa-2.1-api-1.0.0.Final.jar Cannot load JDBC driver class'com.mysql.jdbc.Driver' 缺少mysql-connector-java-5.1.39-bin.jar --> <beanid="sessionFactory"class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"lazy-init="false"> <!--注入datasource,给sessionfactoryBean内setdatasource提供数据源--> <propertyname="dataSource"ref="dataSource"/> <propertyname="configLocation"value="classpath:configuration/hibernate.cfg.xml"></property> <!-- 加载实体类的映射文件位置及名称 路径一定全都用斜杠table/book public static void main(String[] args){ ApplicationContext context; context =new ClassPathXmlApplicationContext("configuration/applicationContext.xml"); DataSourcedataSource = (DataSource)context.getBean(DataSource.class); System.out.println("dataSource.toString()=="+dataSource);
BookService bookService; bookService = context.getBean(BookService.class); bookService.saveBook(new Book(1, "Android源码分析","1002", 45,10)); bookService.saveBook(new Book(2, "iOS源码分析","1012", 43,20)); StringbookName = bookService.findBookById(1); System.out.println(bookName); }
<beansxmlns="http://www.springframework.org/schema/beans"
public class MainClass{
}
这么多代码写好以后,存储一本新书就非常简单了。首先Spring通过读取configuration里的xml文件得到配置好的context,然后context再通过getBean获取实体类,并用实体类进行数据库操作。我们可以看到多次运行后数据库里面加了很多条目。
具体运行结果,上图:
本教程参考了如下:http://www.linuxidc.com/Linux/2016-03/129331.htm
0 0
- Spring与Hibernate整合实现(SH框…
- spring与hibernate整合
- Spring与Hibernate整合
- hibernate 与spring 整合
- Spring与Hibernate整合
- spring与hibernate整合
- Spring 与Hibernate 整合
- Spring与Hibernate整合
- Spring与Hibernate整合
- Spring与HIbernate整合
- Spring与Hibernate整合
- Spring与Hibernate整合
- Spring与Hibernate整合
- Spring与Hibernate整合
- hibernate与spring整合
- Spring与Hibernate整合
- Spring与hibernate整合
- Spring整合Hibernate实现datetime类型比较与分页查询
- Spring中IOC,控制反转(二)——带x…
- 主攻ASP.NET MVC4.0之重生:ASP.NET MVC使用JSONP
- Java性能垫底的真相(别的测试你都…
- util.NestedServletException:&nbs…
- org.springframework.core.NestedI…
- Spring与Hibernate整合实现(SH框…
- 系统的简单注解
- 从最基本的Netbeans默认Servlet项…
- 利用MFC中的picture control 控件显示图像
- 从最基本的Netbeans默认Servlet项…
- java动态代理之cglib动态代理实现
- 满屏幕的线程Hibernate结合Servlet…
- SSH框架特例实战【一】(SpringMVC…
- 为何有DAO与Service层?为何先搞Da…