Hibernate5的学习笔记(二)

就像奶茶大续杯一样,让我们继续和Hibernate打交道,捧好温热的奶茶在这个寒冬里,继续Hibernate的学习。
1、我们的配置hibernate.cfg.xml文件的主要作用就是创建一个sessionFactory,其会通过property配置一些数据库的连接,

也会配置Hibernate的相关属性比如方言、自动创建表机制、格式化sql等,还有就是持久化类的所在路径。

当只是用Hibernate的时候主要是用Hibernate从配置文件里获取sessionFactory,再从sessionFactory中取session,再用session对持久化对象进行操作。

2、hibernate默认加载就是名为hibernate.cfg.xml的配置文件,这是在源代码里面的

public Configuration configure() throws HibernateException {
     //1.StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME的值是"hibernate.cfg.xml"
        return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME );
    }

3、配置SeesionFactory的方式有两种,一种是通过DataSource来配置sessionFactory,另一种是通过Hibernate.cxg.xml来配置。通过DataSource的方法,是Datasource数据源是注入给sessionfactory的SessionFactory是基于dataSource上建立的。

4、在单独使用hibernate的方法时,我们应该这样做

  • a、配置好applicationContext.xml一般放在对应的Service的实现包下xxx\src\main\resources\applicationContext.xml
  • <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="
    		http://www.springframework.org/schema/beans
    		http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    		http://www.springframework.org/schema/context
    		http://www.springframework.org/schema/context/spring-context-4.2.xsd
    		http://www.springframework.org/schema/aop
    		http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
    		http://www.springframework.org/schema/tx
    		http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
    
        <!-- 用于持有ApplicationContext,可以使用SpringContextHolder.getBean('xxxx')的静态方法得到spring bean对象
         该工具类主要用于:那些没有归入spring框架管理的类却要调用spring容器中的bean提供的工具类。
    
          在spring中要通过IOC依赖注入来取得对应的对象,但是该类通过实现ApplicationContextAware接口,
          以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext.
         -->
        <bean id="springContextHolder" class="com.mp.jdbc.context.SpringContextHolder" lazy-init="false"/>
    
        <!-- 扫描路径不扫描controller
        如果某个类的头上带有特定的注解@Component,@Repository,@Service,@Controller,就会将这个对象作为Bean注册进Spring容器。
        启用了对类包进行扫描以实施注释驱动 Bean 定义的功能,同时还启用了注释驱动自动注入的功能
        -->
        <context:component-scan base-package="com.test">
            <context:exclude-filter type="annotation"
                                    expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    
        <!-- 自动注入properties文件中
        DecryptPropertyPlaceholderConfigurer在加载上下文的时候,可以在XML配置文件中加入外部属性文件并加密,
        当然也可以指定外部文件的编码
        location指向配置文件的位置
         设置为lazy的bean将不会在ApplicationContext启动时提前被实例化,而是第一次向容器通过getBean索取bean时实例化的。-->
        <bean id="propertyConfigurer" class="com.mp.jdbc.config.DecryptPropertyPlaceholderConfigurer"
              p:location="classpath:jdbc.properties" lazy-init="true"/>
        <!-- 配置Hibernate事务管理器 -->
        <bean id="sessionFactory"
              class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
            <!--datasource数据源是注入给sessionfactory的SessionFactory是基于dataSource上建立的-->
            <property name="dataSource" ref="dataSource"/>
            <property name="packagesToScan">
                <list>
                    <!-- 可以加多个包 -->
                    <value>com.test.entity</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop>
                    <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</prop>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.format_sql">true</prop>
                </props>
            </property>
        </bean>
    
        <!-- 配置数据源 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"
              p:driverClassName="${master.driverClass}"
              p:url="${master.jdbcUrl}"
              p:username="${master.user}"
              p:password="${master.password}"
              p:initialSize="${master.initialPoolSize}"
              p:minIdle="${master.minPoolSize}"
              p:maxActive="${master.maxPoolSize}"
              p:maxWait="${master.maxWait}"
              p:timeBetweenEvictionRunsMillis="${master.timeBetweenEvictionRunsMillis}"
              p:minEvictableIdleTimeMillis="${master.minEvictableIdleTimeMillis}"
              p:validationQuery="${master.validationQuery}"
              p:testWhileIdle="${master.testWhileIdle}"
              p:testOnBorrow="${master.testOnBorrow}"
              p:testOnReturn="${master.testOnReturn}"
              p:poolPreparedStatements="${master.poolPreparedStatements}"
              p:maxPoolPreparedStatementPerConnectionSize="${master.maxPoolPreparedStatementPerConnectionSize}"/>
    
        <!-- 配置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"/>
    
    
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="insert*" propagation="REQUIRED"/>
                <tx:method name="update*" propagation="REQUIRED"/>
                <tx:method name="delete*" propagation="REQUIRED"/>
                <tx:method name="select*" read-only="true"/>
                <tx:method name="*" rollback-for="java.lang.Exception" timeout="10" />
            </tx:attributes>
        </tx:advice>
    
        <!-- 通过aop定义事务增强切面  -->
        <aop:config>
            <aop:pointcut expression="execution(* com.test.dao.impl.*.*(..))"
                          id="txPointCut"/>
            <!-- 引用事务增强 -->
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
        </aop:config>
    </beans>

    b、配置jdbc.properties

    jdbc.master=master
    master.key=21231312
    master.driverClass=com.mysql.jdbc.Driver
    #master.jdbcUrl=120.0.0.1
    #root 填你自己的账号,密码,这里的属性配置只是换了一种形式,之后会通过spring读取到
    
    master.user=test
    master.password=test
    master.filters=stat
    master.initialPoolSize=5
    master.minPoolSize=5
    master.maxPoolSize=15
    master.maxWait=20000
    master.timeBetweenEvictionRunsMillis=60000
    master.minEvictableIdleTimeMillis=300000
    master.validationQuery=SELECT 1
    master.testWhileIdle=true
    master.testOnBorrow=false
    master.testOnReturn=false
    master.poolPreparedStatements=false
    master.maxPoolPreparedStatementPerConnectionSize=200
    

    c、根据自己的实际情况来,在生成的实体类上打上注解,@Column这个注解有些属性

    @Target({ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Column {
        //被标注字段在数据库表中所对应字段的名称
        String name() default "";
        //表示该字段是否为唯一标识,默认为false。同@Table标记中的@UniqueConstraint
        boolean unique() default false;
        //该字段是否可以为null值,默认为true
        boolean nullable() default true;
        //在使用“INSERT”脚本插入数据时,是否需要插入该字段的值,一般多用于只读的属性
        boolean insertable() default true;
        //在使用“UPDATE”脚本插入数据时,是否需要更新该字段的值,一般多用于只读的属性
        boolean updatable() default true;
        //创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用,但DB中表已经建好就可不用
        String columnDefinition() default "";
        //定义了包含当前字段的表名
        String table() default "";
        //字段的长度,当字段的类型为varchar时,该属性才有效
        int length() default 255;
        //表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数。
        int precision() default 0;
    
        int scale() default 0;
    }

    d、为你操作的持久类设置值,这个操作一般都在Service层中

                    XXXPO xxxPO = new XXXPO();
                    xxxPO.setCompanyId(companyId);
                    xxxPO.setType(type);
                        
                xxxPO.setCreateTime(DateTimeHelper.long2TimeStamp(System.currentTimeMillis()));
                   XXXDao.insertRedPoint(redPoint);

    e、在DAO层使用@Repository 和@Resource注解和对应的语句进行持久化操作,以下列举了多种的Hibernate查询的方法

    
    /*当Service需要使用Spring创建的名字叫“XXXXDao”的XXXXDaoImpl实例时,
      就可以使用@Resource(name = "userDao")注解告诉Spring,
      Spring把创建好的userDao注入给Service即可。
      注解在持久层中,具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能
    */
    @Repository 
    public class XXXXDaoImpl extends AbstractDao implementsXXXXDao {
    
        private static final Logger logger = LoggerFactory.getLogger(XXXXDaoImpl.class);
    
        @Resource  用来装配bean
        private SessionFactory sessionFactory;
    
        private Session getSession() {
            return sessionFactory.getCurrentSession();
        }
    
        private Connection conn;
    
        public XXXXDaoImpl() {
        }
    
        public XXXXDaoImpl(Connection con) {
            this.conn = con;
        }
    
        @Override
        public void updateCheckCount(Integer announcementId) throws SQLException {
            /**
             * 对象查询(Query By Criteria)
             * 1、CriteriaBuilder可以用于创建CriteriaQuery、CriteriaUpdate和CriteriaDelete。
             * 除此之外类似count、max等函数也是由CriteriaBuilder来创建的
             * 2、调用criteriaBuilder.createQuery来创建CriteriaQuery。
             * 其中createQuery的参数是Query返回值类型
             * 3、调用query.from(Order.class),参数是对应于数据库里表的实体类,
             * query.from类似于sql中的from语句,该方法的执行等价于sql中的from order。
             * 4、调用 query.select创建映射,query.select(criteriaBuilder.count(root.get(“id”)))等价于select count(id)。
             * 如果执行query.select(root)则等价于select *。
             * 5、使用CriteriaBuilder构造查询条件Predicate,该predicate也就是在where后面的条件子句。
             * 6、getSession().createQuery(criteriaQuery).uniqueResultOptional()最后执行查询获取数据
             */
            CriteriaBuilder builder = getSession().getCriteriaBuilder();
            CriteriaQuery<XXXXPO> criteriaQuery = builder.createQueryXXXXPO.class);
            
            Root<AnnouncementPO> root = criteriaQuery.from(AnnouncementPO.class);
            criteriaQuery.select(root);
            criteriaQuery.where(builder.equal(root.get("id"), announcementId));
            Optional<XXXXPO> xxxxPO =  getSession().createQuery(criteriaQuery).uniqueResultOptional();
            //如果Optional实例有值则将其返回,否则返回orElse方法传入的参数
            XxxxPO xxxx = announcementPO.orElse(null);
            getSession().save(announcement);
        }
    
    
            /**
             1、主键查询的方法有两种方法:get()和load()支持懒加载
             */
        User u = (User) session.get(User.class, 1);
            User u = (User) session.load(User.class, 1);
    
    
            /**
             * 2、HRL查询,查询全部信息,支持方法链的编程,即直接调用list()方法
             * 注意HRL查询的是实体类的名称,不是数据表的名称,特别注意这一点
             */
            //2.1查询所有 会得到list集合 Query q=session.createQuery("from User");
            //2.2 条件查询 (包括正序asc倒序desc)如下
            Query query = session.createQuery("from Good where gname = ? and gmono =?");
            query.setParameter(0, "面包");
            query.setParameter(1, "奶油面包");
            List<Good> list = query.list();
            //2.3 分页查询
            Query query = session.createQuery("from Good");
            //2.3.1设置第一个要查询的位置(计算公式:(当前页数-1)*每页的记录数)
            query.setFirstResult(0);
            //2.3.2设置每页显示的最大记录数
            query.setMaxResults(3);
            // 2.3.3使用Query对象的list方法得到数据集合
            List<Good> list = query.list();
            //2.4聚集函数查询
            Query query = session.createQuery("select count(*) from Good");
            Object obj = query.uniqueResult();//获取结果(结果为long类型)
            Long long1 = (Long) obj;//转化为long(类型为long,转为int会报错)
            int count = long1.intValue();
            /**
             *2.5多表查询和sql语法一样
             * 内连接查询
             * 显示内连接
             * select * from customers c inner join orders o on c.cid = o.cno;
             * 隐式内连接
             * select * from customers c,orders o where c.cid = o.cno;
    
             * 外连接查询
             * 左外连接
             * select * from customers c left join orders o on c.cid = o.cno;
             * 右外连接
             * select * from customers c right join orders o on c.cid = o.cno;
             */
    
    
    
            /**
             3、完全的面向对象的查询
             */
            //3.1. 简单查询,使用的是Criteria接口
            List<Customer> list = session.createCriteria(Customer.class).list();
            //3.2 排序查询
            Criteria criteria = session.createCriteria(Linkman.class);
            criteria.addOrder(Order.desc("id"));
            List<Linkman> list = criteria.list();
    
            //3.3分页查询
            Criteria criteria = session.createCriteria(Linkman.class);
            criteria.addOrder(Order.desc("lkm_id"));
            criteria.setFirstResult(0);
            criteria.setMaxResults(3);
            List<Linkman> list = criteria.list();
            /**3.4条件查询
             * 条件查询使用Criteria接口的add方法,用来传入条件。
             * 使用Restrictions的添加条件的方法,来添加条件,例如:
             * Restrictions.eq           -- 相等
             * Restrictions.gt           -- 大于号
             * Restrictions.ge           -- 大于等于
             * Restrictions.lt           -- 小于
             * Restrictions.le           -- 小于等于
             * Restrictions.between      -- 在之间
             * Restrictions.like         -- 模糊查询
             * Restrictions.in           -- 范围
             * Restrictions.and          -- 并且
             * Restrictions.or           -- 或者
             */
            Criteria criteria = session.createCriteria(User.class);
            //a、添加条件
            criteria.add(Restrictions.eq("id", 1));
            //查询全部,没有sql语句
            List<User> list = criteria.list();
            //b、多条件
            Criteria criteria = session.createCriteria(Linkman.class);
            // 设置排序
            criteria.addOrder(Order.desc("lkm_id"));
            // 设置查询条件
            criteria.add(Restrictions.or(Restrictions.eq("lkm_gender", "男"), Restrictions.gt("lkm_id", 3L)));
            List<Linkman> list = criteria.list();
    
            /**
             * 3.5 聚合条件查询 criteria.setProjection()
             */
            Criteria criteria = session.createCriteria(Linkman.class);
            criteria.setProjection(Projections.rowCount());
            List<Number> list = criteria.list();
            Long count = list.get(0).longValue();
            System.out.println(count);
    
    
            /**
             * 4、本地查询sql语句,适合使用复杂的查询,
                或者不想使用HQL或者criteria查询,可以使用本地sql查询
             */
            //sql语句
            SQLQuery sql = session.createSQLQuery("select * from user ");
            SQLQuery sql = session.createSQLQuery("select * from user where id=1 ");
            sql.addEntity(User.class);
            List<User> list = sql.list();
            System.out.println(list);
    
            String sql = "UPDATE USER  SET NAME = ? WHERE id =1";
            getSession().createSQLQuery(sql).setParameter(1, id).executeUpdate();

    小猴,在这边提醒如果只是使用hibernate的话,又想要spring托管,就要在初始化的时候让其起到作用

    扫描二维码关注公众号,回复: 5388117 查看本文章
  • new ClassPathXmlApplicationContext("applicationContext.xml");

猜你喜欢

转载自blog.csdn.net/LCF_lxf_ldy/article/details/84936054