zoukankan      html  css  js  c++  java
  • Spring_Hibernate

    Spring与Hiberante整合

    通过hibernate的学习,我们知道,hibernate主要在hibernate.cfg.xml配置文件中

    接下来我们看一下hibernate的一个配置文件

    hibernate配置文件

    hibernate.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
      "http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
      <session-factory>
        <!-- 指定连接数据库所用的驱动 -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 指定连接数据库的url,其中hibernate是本应用连接的数据库名 -->
        <property name="connection.url">jdbc:mysql://localhost/hibernate_test</property>
        <!-- 指定连接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 指定连接数据库的密码 -->
        <property name="connection.password">cheng</property>
        <!-- 指定连接池里最大连接数 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <!-- 指定连接池里最小连接数 -->
        <property name="hibernate.c3p0.min_size">1</property>
        <!-- 指定连接池里连接的超时时长 -->
        <property name="hibernate.c3p0.timeout">5000</property>
        <!-- 指定连接池里最大缓存多少个Statement对象 -->
        <property name="hibernate.c3p0.max_statements">100</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>
        <property name="hibernate.c3p0.validate">true</property>
        <!-- 指定数据库方言 -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 根据需要自动创建数据表 -->
        <property name="hbm2ddl.auto">update</property><!--①-->
        <!-- 显示Hibernate持久化操作所生成的SQL -->
        <property name="show_sql">true</property>
        <!-- 将SQL脚本进行格式化后再输出 -->
        <property name="hibernate.format_sql">true</property>
        <!-- 避免这个错误信息Disabling contextual LOB creation as createClob() method threw error :java.lang.reflect.InvocationTargetException -->
        <property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
        <!-- 罗列所有持久化类的类名 -->
        <mapping class="com.wechat.entity.po.User"/>
        <mapping class="com.wechat.entity.po.Person"/>
      </session-factory>
    </hibernate-configuration>

    置文件的作用

    hibernate.cfg.xml文件的主要作用就是配置了一个session-factory

    1. 在session-factory中主要通过property配置一些数据库的连接信息,我们知道,spring通常会将这种数据库连接用dataSource来表示,这样一来,hibernate.cfg.xml文件中的所有跟数据库连接的都可以干掉了,直接用spring的dataSource,而dataSource也可以用c3p0、dbcp等。
    2. 在session-factory中通过property除了配置一些数据库的连接信息之外,还有一些hibernate的配置,比如方言、自动创建表机制、格式化sql等,这些信息也需要配置起来。
    3. 还有最关键的一个持久化类所在路径的配置

    当不采用spring整合的时候,我们使用hibernate时主要是用hibernate从sessionFactory中去的session,然后用session来操作持久化对象,而sessionFactory来自于配置文件。像下面这样:

    StandardServiceRegistry registry = null;
    SessionFactory sessionFactory = null;
    Session session = null;
    Transaction transaction = null;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     
    @Before
    public void init() {
     
      registry = new StandardServiceRegistryBuilder()
          .configure() // configures settings from hibernate.cfg.xml
          .build();
      sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
      session = sessionFactory.openSession();
      //开始事务
      transaction = session.getTransaction();
      transaction.begin();
    }
     
    @Test
    public void testSaveUser() {
      User user = new User();
      user.setUsername("张学友");
      user.setPassword("jacky");
      user.setRegistDate(sdf.format(new Date()));
      File file = new File("D:"+File.separator+"ubuntu.png");
      String fileName = file.getName();
      String prefix=fileName.substring(fileName.lastIndexOf(".")+1);
      System.out.println(prefix);
      InputStream input = null;
      try {
        input = new FileInputStream(file);
     
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      }
     
      Blob image = null;
      try {
        image = Hibernate.getLobCreator(session).createBlob(input,input.available());
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      user.setUserPic(image);
      session.save(user);
    }
     
    @After
    public void destroy(){
      transaction.commit();
      session.close();
      sessionFactory.close();
      StandardServiceRegistryBuilder.destroy( registry 

    Spring对hibernate的整合就是将上述三点通过spring配置起来,而hibernate最关键的sessionFactroy就是spring的一个bean

    这些理解了整合就简单了,

    SessionFactoryBean

    spring的sessionFactroy像下面这样配置:

    <!-- 加载配置文件 -->
      <context:property-placeholder location="classpath:jdbc.properties"
        file-encoding="utf-8" ignore-unresolvable="true" />
     
      <bean id="sessionFactory"
        class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
          <list>
            <!-- 可以加多个包 -->
            <value>com.wechat.entity.po</value>
          </list>
        </property>
        <property name="hibernateProperties">
          <props>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
          </props>
        </property>
      </bean>

    通过bean的配置可以看出该bean就是hibernate的sessionFactroy

    因为它指向了org.springframework.orm.hibernate5.LocalSessionFactoryBean

    在这个bean中主要配置了上面说的三点:

    1. 数据源dataSource
    2. hibernate的配置,包括方言,输出sql等
    3. 持久化类的位置,通过包进行扫描

    下面给出数据源dataSource的配置

    dataSource

    <!-- 配置数据源 -->
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close" p:driverClass="${jdbc.driverClassName}"
        p:jdbcUrl="${jdbc.url}" p:user="${jdbc.username}" p:password="${jdbc.password}"
        p:testConnectionOnCheckout="${jdbc.c3p0.testConnectionOnCheckout}"
        p:testConnectionOnCheckin="${jdbc.c3p0.testConnectionOnCheckin}"
        p:idleConnectionTestPeriod="${jdbc.c3p0.idleConnectionTestPeriod}"
        p:initialPoolSize="${jdbc.c3p0.initialPoolSize}" p:minPoolSize="${jdbc.c3p0.minPoolSize}"
        p:maxPoolSize="${jdbc.c3p0.maxPoolSize}" p:maxIdleTime="${jdbc.c3p0.maxIdleTime}" />

    还有数据库的连接信息

    jdbc.properties

    #-----------------------------------------------------
    # 数据库配置
    #-----------------------------------------------------
    #服务器地址
    host=127.0.0.1
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://${host}:3306/hibernate_test
    jdbc.username=root
    jdbc.password=cheng
     
    #-----------------------------------------------------
    # 适用于c3p0的配置
    #-----------------------------------------------------
    #-----------------------------------------------------
    # c3p0反空闲设置,防止8小时失效问题28800
    #-----------------------------------------------------
    #idleConnectionTestPeriod要小于MySQL的wait_timeout
    jdbc.c3p0.testConnectionOnCheckout=false
    jdbc.c3p0.testConnectionOnCheckin=true
    jdbc.c3p0.idleConnectionTestPeriod=3600
    #-----------------------------------------------------
    # c3p0连接池配置
    #-----------------------------------------------------
    #initialPoolSize, minPoolSize, maxPoolSize define the number of Connections that will be pooled.
    #Please ensure that minPoolSize <= maxPoolSize.
    #Unreasonable values of initialPoolSize will be ignored, and minPoolSize will be used instead.
    jdbc.c3p0.initialPoolSize=10
    jdbc.c3p0.minPoolSize=10
    jdbc.c3p0.maxPoolSize=100
    #maxIdleTime defines how many seconds a Connection should be permitted to go unused before being culled from the pool.
    jdbc.c3p0.maxIdleTime=3600
    #-----------------------------------------------------
    # hibernate连接池配置
    #-----------------------------------------------------
    hibernate.connection.driverClass=com.mysql.jdbc.Driver
    hibernate.connection.url=jdbc:mysql://${host}:3306/${dbName}
    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
    hibernate.show_sql=true
    hibernate.format_sql=true
    hibernate.hbm2ddl.auto=update

    配置完这些还有spring强大的事务管理

    <!-- 配置Hibernate事务管理器 -->
      <bean id="transactionManager"
        class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
      </bean>
     
      <!-- 配置事务异常封装 -->
      <bean id="persistenceExceptionTranslationPostProcessor"
        class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
     
      <!-- 基于数据源的事务管理器 -->
      <!-- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" 
        p:dataSource-ref="dataSource" /> -->
     
      <!-- 配合<tx:advice>和<aop:advisor>完成了事务切面的定义 -->
      <!-- 使用强大的切点表达式是语言轻松定义目标方法 -->
      <aop:config proxy-target-class="true">
        <!-- 通过aop定义事务增强切面 -->
        <aop:pointcut expression=" execution(* com.wechat.service..*(..))"
          id="serviceMethod" />
        <!-- 引用事务增强 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
      </aop:config>
      <!-- 事务增强 -->
      <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 事务属性定义 -->
        <tx:attributes>
          <tx:method name="*" />
        </tx:attributes>
      </tx:advice>

    好了,这些配置好之后就可以使用在spring中配置的sessionFactroy了

    UserDao

    package com.wechat.dao;
     
    import java.util.List;
     
    import com.wechat.entity.po.User;
     
    public interface UserDao {
      // 得到所有用户
      public List<User> getAllUser();
     
      // 检测用户名是否存在
      public boolean isExists(String username);
     
    }

    实现类

    package com.wechat.dao.impl;
     
    import java.util.ArrayList;
    import java.util.List;
     
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
     
    import com.wechat.dao.UserDao;
    import com.wechat.entity.po.User;
    @Repository
    public class UserDaoImpl implements UserDao {
      //注入sessionFactory
      @Autowired
      private SessionFactory sessionFactory;
     
      @SuppressWarnings("unchecked")
      @Override
      public List<User> getAllUser() {
        List<User> userList = new ArrayList<User>();
        String hsql="from User";
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery(hsql);
        userList = query.list();
        return userList;
      }
     
      @Override
      public boolean isExists(String username) {
        Query query = sessionFactory.openSession()
            .createQuery("from User u where u.username = :username").setParameter("username", username);
        System.out.println(query.list().size());
        return query.list().size()>0?true:false;
      }
     
    }

    UserService

    package com.wechat.service.user;
     
    import java.util.List;
     
    import com.wechat.entity.po.User;
     
    public interface UserService {
      public List<User> getAllUser();
      public boolean isExists(String username);
     
    }

    实现类

    package com.wechat.service.user.impl;
     
    import java.util.List;
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.stereotype.Service;
     
    import com.wechat.dao.UserDao;
    import com.wechat.entity.po.User;
    import com.wechat.service.user.UserService;
    @Service
    public class UserServiceImpl implements UserService {
      @Autowired
      private UserDao userDao;
      @Override
      public List<User> getAllUser() {
        return userDao.getAllUser();
      }
      @Override
      @Cacheable(cacheNames="isExists", key="#username")
      public boolean isExists(String username) {
        return userDao.isExists(username);
      }
     
    }

    因为事务管理是配置在service层,所以用service来测试

    测试

    package com.wechat.dao;
     
    import java.util.List;
     
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
     
    import com.wechat.entity.po.User;
    import com.wechat.service.user.UserService;
     
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:spring/spring-core.xml" })
    public class UserServiceTest {
      @Autowired
      private UserService userService;
     
      @Test
      public void test() {
        List<User> userList = userService.getAllUser();
        for(User user:userList){
          System.out.println(user.getUsername());
        }
     
      }
     
    }
  • 相关阅读:
    86. Partition List
    328. Odd Even Linked List
    19. Remove Nth Node From End of List(移除倒数第N的结点, 快慢指针)
    24. Swap Nodes in Pairs
    2. Add Two Numbers(2个链表相加)
    92. Reverse Linked List II(链表部分反转)
    109. Convert Sorted List to Binary Search Tree
    138. Copy List with Random Pointer
    为Unity的新版ugui的Prefab生成预览图
    ArcEngine生成矩形缓冲区
  • 原文地址:https://www.cnblogs.com/tanlei-sxs/p/10194697.html
Copyright © 2011-2022 走看看