Lesson39_Hibernate

Hibnate框架笔记

1、基本概念

1.1、简介

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的JaveEE架构中取代CMP,完成数据持久化**的重任。

  • DBUtils也是对JDBC的封装
  • 它将POJO与数据库表建立映射关系,是一个全自动的orm框架
  • POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans
  • hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
  • Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用

1.2、总结Hibernate

  • Hibernate是一个数据持久化层的ORM框架,它的主要功能就是把对象映射到表中,操作API,只需要将一个对象存储到数据库,不需要写sql语句
  • Hibernate提供了对关系型数据库增删改成操作

1.3、orm

对象关系映射,可以认为是讲实体类与数据库表相互关联,形成对应的映射关系,使得每个人model与一张表相关联,字段与属性相互形成映射关系。

  • 对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping)
  • 对象和表字段进行对应
  • 是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
  • Object:对象,java对象,此处特指JavaBean,Model
  • Relational:关系,二维表,数据库中的表。
  • Mapping:映射

1.4、主流ORM框架

  • JPA Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系(只有接口规范)
  • Hibernate 最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL
  • MyBatis 本是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架
  • Apache DBUtils 、Spring JDBCTemplate

1.5、Hibernate的优点

  1. Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
  2. Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
  3. Hibernate使用java的反射机制
  4. Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,有一对一到多对多的各种复杂关系映射

1.4、实体类

实体类是hibernate中的类建模规范,用entity、model、pojo表示,一般有一下要求:

  1. 实体类中提供无参的构造方法
  2. 实体类中提供每个属性的public的getter与setter方法
  3. 有一个可以作为主键的属性
  4. 属性尽量使用基本类型的包装类
  5. 不要用final对实体进行修饰

2、配置文件与jar包

2.1、hibernate的使用步骤

  • 下载hibernate 的jar包,并导入到项目中(http://hibernate.org/orm/)
  • 创建数据库和表
  • 配置核心配置文件hibernate.cfg.xml【这个文件有连接数据库的配置】
  • 编写映射文件hibernate mapping(*.hbm.xml),【声明对象如何关联数据库表字段】
  • 调用hibernate的api

2.1、jar包

  • 这里我们使用3.6.0的版本开发,4.0开发是建议使用注解
  • 所需要导入的jar包,如下图,然后再导入一个mysql数据库连接驱动
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述
  • maven下的jar包
<!--hibernate支持jpa规范-->
    <dependency>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.1-api</artifactId>
      <version>1.0.2.Final</version>
    </dependency>
    <!--字节码增强-->
    <dependency>
      <groupId>org.javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.26.0-GA</version>
    </dependency>
    <!--日志管理,整合log4j-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.8.0-beta4</version>
    </dependency>
    <dependency>
      <groupId>org.jboss.logging</groupId>
      <artifactId>jboss-logging</artifactId>
      <version>3.4.1.Final</version>
    </dependency>
    <!--事物规范-->
    <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
    </dependency>
    <dependency>
      <groupId>org.jboss.spec.javax.transaction</groupId>
      <artifactId>jboss-transaction-api_1.2_spec</artifactId>
      <version>1.1.1.Final</version>
    </dependency>
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

2.2、配置文件

2.2.1、核心配置(hibernate.cfg.xml)
  • 将hibernate.cfg.xml放入src下
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <!--连接数据库的属性-->
    <property name="connection.url">jdbc:mysql://localhost:3306/test?serverTimezone=Hongkong</property>
    <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
    <property name="connection.username">root</property>
    <property name="connection.password">root</property>
    <!--
    数据库方言,每个数据库都有自己的方言。如做分页
    mysql:limit
    Oracle:rownum
    -->
    <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
    <!--运行显示SQL语句-->
    <property name="show_sql">true</property>
    <!--按照格式打印出SQL语句-->
    <property name="format_sql">true</property>
    <!--
    Hibernate映射与DDL语句策略。
    update:如果操作数据库没有对应表就会自动创建表。
    		如果数据库字段与实体类属性不一致,则会更新表。
    create:每次启动都会创建新表。
    create-drop:每次启动都会创建新表,关闭会自动删除表。
    validate:检查配置文件与数据库的字段,如果不一致则抛异常。
    -->
    <property name="hibernate.hibernate.hbm2ddl.auto">update</property>
    <!--自动提交事物,对insert语句有效-->
    <property name="hibernate.connection.autocommit">true</property>
    <!--开启与当前线程绑定的session的功能-->
    <property name="hibernate.current_session_context_class">thread</property>
    <!--需要映射的配置资源-->
    <!--<mapping resource="com/iotek/entity/user.hbm.xml"/>-->
  </session-factory>
</hibernate-configuration>
2.2.2、核心配置(hibernate.properties)
######################
### Query Language ###
######################

## define query language constants / function names

hibernate.query.substitutions yes 'Y', no 'N'


## select the classic query parser

#hibernate.query.factory_class org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory



#################
### Platforms ###
#################

## JNDI Datasource

#hibernate.connection.datasource jdbc/test
#hibernate.connection.username db2
#hibernate.connection.password db2


## HypersonicSQL

hibernate.dialect org.hibernate.dialect.HSQLDialect
hibernate.connection.driver_class org.hsqldb.jdbcDriver
hibernate.connection.username sa
hibernate.connection.password
hibernate.connection.url jdbc:hsqldb:./build/db/hsqldb/hibernate
#hibernate.connection.url jdbc:hsqldb:hsql://localhost
#hibernate.connection.url jdbc:hsqldb:test

## H2 (www.h2database.com)
#hibernate.dialect org.hibernate.dialect.H2Dialect
#hibernate.connection.driver_class org.h2.Driver
#hibernate.connection.username sa
#hibernate.connection.password
#hibernate.connection.url jdbc:h2:mem:./build/db/h2/hibernate
#hibernate.connection.url jdbc:h2:testdb/h2test
#hibernate.connection.url jdbc:h2:mem:imdb1
#hibernate.connection.url jdbc:h2:tcp://dbserv:8084/sample; 	
#hibernate.connection.url jdbc:h2:ssl://secureserv:8085/sample; 	
#hibernate.connection.url jdbc:h2:ssl://secureserv/testdb;cipher=AES

## MySQL

#hibernate.dialect org.hibernate.dialect.MySQLDialect
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql:///test
#hibernate.connection.username gavin
#hibernate.connection.password


## Oracle

#hibernate.dialect org.hibernate.dialect.Oracle8iDialect
#hibernate.dialect org.hibernate.dialect.Oracle9iDialect
#hibernate.dialect org.hibernate.dialect.Oracle10gDialect
#hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
#hibernate.connection.username ora
#hibernate.connection.password ora
#hibernate.connection.url jdbc:oracle:thin:@localhost:1521:orcl
#hibernate.connection.url jdbc:oracle:thin:@localhost:1522:XE


## PostgreSQL

#hibernate.dialect org.hibernate.dialect.PostgreSQLDialect
#hibernate.connection.driver_class org.postgresql.Driver
#hibernate.connection.url jdbc:postgresql:template1
#hibernate.connection.username pg
#hibernate.connection.password


## DB2

#hibernate.dialect org.hibernate.dialect.DB2Dialect
#hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver
#hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver
#hibernate.connection.url jdbc:db2://localhost:50000/somename
#hibernate.connection.url jdbc:db2:somename
#hibernate.connection.username db2
#hibernate.connection.password db2

## TimesTen

#hibernate.dialect org.hibernate.dialect.TimesTenDialect
#hibernate.connection.driver_class com.timesten.jdbc.TimesTenDriver
#hibernate.connection.url jdbc:timesten:direct:test
#hibernate.connection.username
#hibernate.connection.password 

## DB2/400

#hibernate.dialect org.hibernate.dialect.DB2400Dialect
#hibernate.connection.username user
#hibernate.connection.password password

## Native driver
#hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver
#hibernate.connection.url jdbc:db2://systemname

## Toolbox driver
#hibernate.connection.driver_class com.ibm.as400.access.AS400JDBCDriver
#hibernate.connection.url jdbc:as400://systemname


## Derby (not supported!)

#hibernate.dialect org.hibernate.dialect.DerbyDialect
#hibernate.connection.driver_class org.apache.derby.jdbc.EmbeddedDriver
#hibernate.connection.username
#hibernate.connection.password
#hibernate.connection.url jdbc:derby:build/db/derby/hibernate;create=true


## Sybase

#hibernate.dialect org.hibernate.dialect.SybaseDialect
#hibernate.connection.driver_class com.sybase.jdbc2.jdbc.SybDriver
#hibernate.connection.username sa
#hibernate.connection.password sasasa
#hibernate.connection.url jdbc:sybase:Tds:co3061835-a:5000/tempdb


## Mckoi SQL

#hibernate.dialect org.hibernate.dialect.MckoiDialect
#hibernate.connection.driver_class com.mckoi.JDBCDriver
#hibernate.connection.url jdbc:mckoi:///
#hibernate.connection.url jdbc:mckoi:local://C:/mckoi1.0.3/db.conf
#hibernate.connection.username admin
#hibernate.connection.password nimda


## SAP DB

#hibernate.dialect org.hibernate.dialect.SAPDBDialect
#hibernate.connection.driver_class com.sap.dbtech.jdbc.DriverSapDB
#hibernate.connection.url jdbc:sapdb://localhost/TST
#hibernate.connection.username TEST
#hibernate.connection.password TEST
#hibernate.query.substitutions yes 'Y', no 'N'


## MS SQL Server

#hibernate.dialect org.hibernate.dialect.SQLServerDialect
#hibernate.connection.username sa
#hibernate.connection.password sa

## JSQL Driver
#hibernate.connection.driver_class com.jnetdirect.jsql.JSQLDriver
#hibernate.connection.url jdbc:JSQLConnect://1E1/test

## JTURBO Driver
#hibernate.connection.driver_class com.newatlanta.jturbo.driver.Driver
#hibernate.connection.url jdbc:JTurbo://1E1:1433/test

## WebLogic Driver
#hibernate.connection.driver_class weblogic.jdbc.mssqlserver4.Driver
#hibernate.connection.url jdbc:weblogic:mssqlserver4:1E1:1433

## Microsoft Driver (not recommended!)
#hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver
#hibernate.connection.url jdbc:microsoft:sqlserver://1E1;DatabaseName=test;SelectMethod=cursor

## The New Microsoft Driver 
#hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver
#hibernate.connection.url jdbc:sqlserver://localhost

## jTDS (since version 0.9)
#hibernate.connection.driver_class net.sourceforge.jtds.jdbc.Driver
#hibernate.connection.url jdbc:jtds:sqlserver://1E1/test

## Interbase

#hibernate.dialect org.hibernate.dialect.InterbaseDialect
#hibernate.connection.username sysdba
#hibernate.connection.password masterkey

## DO NOT specify hibernate.connection.sqlDialect

## InterClient

#hibernate.connection.driver_class interbase.interclient.Driver
#hibernate.connection.url jdbc:interbase://localhost:3060/C:/firebird/test.gdb

## Pure Java

#hibernate.connection.driver_class org.firebirdsql.jdbc.FBDriver
#hibernate.connection.url jdbc:firebirdsql:localhost/3050:/firebird/test.gdb


## Pointbase

#hibernate.dialect org.hibernate.dialect.PointbaseDialect
#hibernate.connection.driver_class com.pointbase.jdbc.jdbcUniversalDriver
#hibernate.connection.url jdbc:pointbase:embedded:sample
#hibernate.connection.username PBPUBLIC
#hibernate.connection.password PBPUBLIC


## Ingres

## older versions (before Ingress 2006)

#hibernate.dialect org.hibernate.dialect.IngresDialect
#hibernate.connection.driver_class ca.edbc.jdbc.EdbcDriver
#hibernate.connection.url jdbc:edbc://localhost:II7/database
#hibernate.connection.username user
#hibernate.connection.password password

## Ingres 2006 or later

#hibernate.dialect org.hibernate.dialect.IngresDialect
#hibernate.connection.driver_class com.ingres.jdbc.IngresDriver
#hibernate.connection.url jdbc:ingres://localhost:II7/database;CURSOR=READONLY;auto=multi
#hibernate.connection.username user
#hibernate.connection.password password

## Mimer SQL

#hibernate.dialect org.hibernate.dialect.MimerSQLDialect
#hibernate.connection.driver_class com.mimer.jdbc.Driver
#hibernate.connection.url jdbc:mimer:multi1
#hibernate.connection.username hibernate
#hibernate.connection.password hibernate


## InterSystems Cache

#hibernate.dialect org.hibernate.dialect.Cache71Dialect
#hibernate.connection.driver_class com.intersys.jdbc.CacheDriver
#hibernate.connection.username _SYSTEM
#hibernate.connection.password SYS
#hibernate.connection.url jdbc:Cache://127.0.0.1:1972/HIBERNATE


#################################
### Hibernate Connection Pool ###
#################################

hibernate.connection.pool_size 1



###########################
### C3P0 Connection Pool###
###########################

#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false



##############################
### Proxool Connection Pool###
##############################

## Properties for external configuration of Proxool

hibernate.proxool.pool_alias pool1

## Only need one of the following

#hibernate.proxool.existing_pool true
#hibernate.proxool.xml proxool.xml
#hibernate.proxool.properties proxool.properties



#################################
### Plugin ConnectionProvider ###
#################################

## use a custom ConnectionProvider (if not set, Hibernate will choose a built-in ConnectionProvider using hueristics)

#hibernate.connection.provider_class org.hibernate.connection.DriverManagerConnectionProvider
#hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider
#hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider
#hibernate.connection.provider_class org.hibernate.connection.ProxoolConnectionProvider



#######################
### Transaction API ###
#######################

## Enable automatic flush during the JTA beforeCompletion() callback
## (This setting is relevant with or without the Transaction API)

#hibernate.transaction.flush_before_completion


## Enable automatic session close at the end of transaction
## (This setting is relevant with or without the Transaction API)

#hibernate.transaction.auto_close_session


## the Transaction API abstracts application code from the underlying JTA or JDBC transactions

#hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory


## to use JTATransactionFactory, Hibernate must be able to locate the UserTransaction in JNDI
## default is java:comp/UserTransaction
## you do NOT need this setting if you specify hibernate.transaction.manager_lookup_class

#jta.UserTransaction jta/usertransaction
#jta.UserTransaction javax.transaction.UserTransaction
#jta.UserTransaction UserTransaction


## to use the second-level cache with JTA, Hibernate must be able to obtain the JTA TransactionManager

#hibernate.transaction.manager_lookup_class org.hibernate.transaction.JBossTransactionManagerLookup
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.WeblogicTransactionManagerLookup
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.WebSphereTransactionManagerLookup
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.OrionTransactionManagerLookup
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.ResinTransactionManagerLookup



##############################
### Miscellaneous Settings ###
##############################

## print all generated SQL to the console

#hibernate.show_sql true


## format SQL in log and console

hibernate.format_sql true


## add comments to the generated SQL

#hibernate.use_sql_comments true


## generate statistics

#hibernate.generate_statistics true


## auto schema export

#hibernate.hbm2ddl.auto create-drop
#hibernate.hbm2ddl.auto create
#hibernate.hbm2ddl.auto update
#hibernate.hbm2ddl.auto validate


## specify a default schema and catalog for unqualified tablenames

#hibernate.default_schema test
#hibernate.default_catalog test


## enable ordering of SQL UPDATEs by primary key

#hibernate.order_updates true


## set the maximum depth of the outer join fetch tree

hibernate.max_fetch_depth 1


## set the default batch size for batch fetching

#hibernate.default_batch_fetch_size 8


## rollback generated identifier values of deleted entities to default values

#hibernate.use_identifer_rollback true


## enable bytecode reflection optimizer (disabled by default)

#hibernate.bytecode.use_reflection_optimizer true



#####################
### JDBC Settings ###
#####################

## specify a JDBC isolation level

#hibernate.connection.isolation 4


## enable JDBC autocommit (not recommended!)

#hibernate.connection.autocommit true


## set the JDBC fetch size

#hibernate.jdbc.fetch_size 25


## set the maximum JDBC 2 batch size (a nonzero value enables batching)

#hibernate.jdbc.batch_size 5
#hibernate.jdbc.batch_size 0


## enable batch updates even for versioned data

hibernate.jdbc.batch_versioned_data true


## enable use of JDBC 2 scrollable ResultSets (specifying a Dialect will cause Hibernate to use a sensible default)

#hibernate.jdbc.use_scrollable_resultset true


## use streams when writing binary types to / from JDBC

hibernate.jdbc.use_streams_for_binary true


## use JDBC 3 PreparedStatement.getGeneratedKeys() to get the identifier of an inserted row

#hibernate.jdbc.use_get_generated_keys false


## choose a custom JDBC batcher

# hibernate.jdbc.factory_class


## enable JDBC result set column alias caching 
## (minor performance enhancement for broken JDBC drivers)

# hibernate.jdbc.wrap_result_sets


## choose a custom SQL exception converter

#hibernate.jdbc.sql_exception_converter



##########################
### Second-level Cache ###
##########################

## optimize cache for minimal "puts" instead of minimal "gets" (good for clustered cache)

#hibernate.cache.use_minimal_puts true


## set a prefix for cache region names

hibernate.cache.region_prefix hibernate.test


## disable the second-level cache

#hibernate.cache.use_second_level_cache false


## enable the query cache

#hibernate.cache.use_query_cache true


## store the second-level cache entries in a more human-friendly format

#hibernate.cache.use_structured_entries true


## choose a cache implementation

#hibernate.cache.region.factory_class org.hibernate.cache.infinispan.InfinispanRegionFactory
#hibernate.cache.region.factory_class org.hibernate.cache.infinispan.JndiInfinispanRegionFactory
#hibernate.cache.region.factory_class org.hibernate.cache.internal.EhCacheRegionFactory
#hibernate.cache.region.factory_class org.hibernate.cache.internal.SingletonEhCacheRegionFactory
hibernate.cache.region.factory_class org.hibernate.cache.internal.NoCachingRegionFactory

## choose a custom query cache implementation

#hibernate.cache.query_cache_factory



############
### JNDI ###
############

## specify a JNDI name for the SessionFactory

#hibernate.session_factory_name hibernate/session_factory


## Hibernate uses JNDI to bind a name to a SessionFactory and to look up the JTA UserTransaction;
## if hibernate.jndi.* are not specified, Hibernate will use the default InitialContext() which
## is the best approach in an application server

#file system
#hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory
#hibernate.jndi.url file:/

#WebSphere
#hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory
#hibernate.jndi.url iiop://localhost:900/
2.2.3、JavaBean映射文件(className.hbm.xml)
  • JavaBean与.hbm.xml文件包属的包和文件名要一致
<?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>
            <!--
            name:指的是实体类模型
            table:是指对应的数据库表
            dynamic-insert:是否动态生成插入语句,如果没有写默认是false。此时
            如果插入的数据有一些字段为空,执行insert语句时依然会插入所有字段,
            如果设置此属性为true,则会根据数据库实际字段数来插入数据。
            dynamic-update:是否动态生成更新语句,与dynamic-insert类似。
            -->
            <class name="com.iotek.entity.User" table="user" dynamic-insert="true" dynamic-update="true">
                <!--
                id,name指模型主键,column指数据库主键。
                generator指主键策略:
                increment:也是自动增长,但是会在数据库中已有id的最大值的基础上
                增加1,如果没有数据则第一条数据为1.当增加到10时删除数据,则下一
                条依然从1开始。但是此方式会有线程并发问题。
                sequence:Oracle数据库中使用。
                hilo:hibernate自己实现,几乎不用。
                native:
                如果是mysql数据库,则是自增,与数据库自增类似,从1开
                始,自己会记住增长的值,也就是当增长到10时删掉所有数据,下一条
                依然是11.
                如果是Oracle,则会根据sequence来增长。
                uuid:一个长字符串,需要把模型的id改为String类型的,保存的时候
                不用自己设置id,hibernate会做。
                assigend:需要手动设置id,如果不收的设置,存储是会报错,要求在
                保存数据前设置id。
                -->
                <id name="id" column="id">
                    <generator class="native"/>
                </id>
                <!--
                每个属性,name指模型属性,column指数据库字段,如果模型与数据库
                字段一样,则可以省略column
                length:设置字段长度。
                type:设置属性的类型,在自动生成表格时会根据设置来生成
                	date类型匹配数据库date类型,显示年月日。
                	time类型匹配数据库time类型,显示时分秒。
                	datetime匹配数据库datetime类型,显示年月日时分秒。
                -->
                <property name="name" type="string" length="6"/>
                <property name="pass"/>
                <property name="age"/>
                <property name="type"/>
            </class>
</hibernate-mapping>
2.2.4、日志打印配置
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=warn, stdout

#log4j.logger.org.hibernate=info
log4j.logger.org.hibernate=debug

### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug

### log just the SQL
#log4j.logger.org.hibernate.SQL=debug

### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug

### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug

### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug

### log cache activity ###
#log4j.logger.org.hibernate.cache=debug

### log transaction activity
#log4j.logger.org.hibernate.transaction=debug

### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
# 以下为经常使用的配置,需要打印的日志可以根据需要选择
# Global logging configuration
# log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3、API

3.1、操作步骤

  • Hibernate的核心配置文件有多种形式
  • hibernate.cfg.xml 通常使用xml配置文件,可以配置内容更丰富。
  • hibernate.properties 用于配置key/value 形式的内容,key不能重复的。配置有很多的局限性。一般不用。【可以进入hibernate-distribution-3.6.10.Final\project\etc目录看内容】
  1. 加载核心配置文件
Configuration cfg = new Configuration().configure();
  1. 创建sessionFactory工厂对象
SessionFactory sessionFactory = cfg.buildSessionFactory();
  1. 创建session会话对象
Session session = sessionFactory.openSession();
  1. 开启事物
Transaction transaction = session.getTransaction();
        transaction.begin();
  1. 加载执行sql操作
session.load(User.class,2);
Session.get(User.class,1);
  1. 提交事物
transaction.commit();
  1. 关闭session会话
session.close();
  1. 关闭sessioFactory
sessionFactory.close();

3.2、加载核心配置文件

3.2.1、直接创建对象加载
  • Configuration对象
  • Configuration对象就是用来加载配置文件
  • Configuration对象就是用来加载配置文件
  • configre()方法加载的是hibernate.cfg.xml
  • 默认情况下,上面两种配置文件都需要放在src目录下
  • 在这里插入图片描述
  • configure(String resource)这个方法可以指定配置文件路径
Configuration cfg = new Configuration()

该方法是直接加载hibernate.propeties文件,但hibernate.propeties文件是key,value格式的,且key不可以重复,所有有局限性,故多用hibernate.cfg.xml文件作为核心文件的格式类加载配置,所有加载hibernate.cfg.xml时用下面方法

3.2.2、通过对象调用方法加载
Configuration cfg = new Configuration().configure();

后面configure方法中可以写参数用来指定核心配置文件,如果不指定则默认去classpath下找hibernate.cfg.xml文件。

3.3、添加映射文件

  1. 在核心配置文件中添加
<mapping resource="com/iotek/entity/user.hbm.xml"/>
  1. 通过Configuration对象添加
  • addResource()方法
//该方法直接去加载路径资源的映射文件
cfg.addResource("URL")
  • addClass()方法
//该方法内部用字符串拼接的方式来加载映射文件,所有映射文件的命名不能随意改变
cfg.addClass(User.class);

以上两种方式如果重复使用,则要看hibernate的版本,有些版本的如果重复加载同一个文件则会报错,有些版本则会覆盖掉前面的文件。
所以一般单独使用一种,防止重复加载映射文件导致程序报错

  • 平时开发中:将hbm.xml映射 配置 在hibernate.cfg.xml

3.4、session与sessionFactory

3.4.1、sessionFactory
  1. sessionFactory是会话工厂,它是用来产生session会话的生产者,类似于是一个数据库连接池,它床建好session会话后通过会话来访问操作数据库。sessionFactory是线程安全的。
  2. SessionFactory 相当于java web连接池,用于管理所有session
  3. SessionFactory 相当于java web连接池,用于管理所有session在这里插入图片描述
  4. sessionFactory 还用于缓存配置信息 (数据库配置信息、映射文件,预定义HQL语句 等)
  5. SessionFactory线程安全,多个线程同时访问时,不会出现线程并发访问问题。
  6. 创建方式
Configuration cfg = new Configuration().configure();
cfg.addClass(User.class);
SessionFactory sessionFactory = cfg.buildSessionFactory();
3.4.2、session会话
  1. session是会话,是用来与数据库建立连接,操作数据库以及对应的配置,类似于数据库连接,它是通过sessionFactory来生产的。
  2. 创建方式
  • openSession()方法创建一个独立的session
Session session = sessionFactory.openSession();
  • 要使用这个方法必须在hibernate.cfg.xml中配置
<property name="hibernate.current_session_context_class">thread</property>
  • hibernate支持,将创建的session绑定到本地线程中,底层使用ThreadLocal,在程序之间共享session。
  • 如果提交或者回滚事务,底层将自动关闭session

通过该方式每次都会创建一个新的session。关闭是需要手动关闭

  • getCurrentSession()方式创建一个关联线程的session
Session currentSession = sessionFactory.getCurrentSession();

通过该方法会创建一个关联线程的session,只要是在同一线程内,都是同一个session。但是要使用该方式创建一个session要先在核心配置文件中进行相应的配置,否则会报错。配置如下

<!--开启与当前线程绑定的session的功能-->
    <property name="hibernate.current_session_context_class">thread</property>

在使用该方式创建的session在某些版本中必须要收到开启提价事物,且事物提交或者是回滚时session自动关闭,不需要手动关闭。

  • 案例代码
  • 在这里插入图片描述

3.5、事物(Transaction)

  1. hibernate中默认是要手动提交事物,但是也可以通过配置来实现自动提交。在框架整合之后事物的管理是交给spring来管理的。
  2. 手动提交事物
//获取事物对象
        Transaction transaction = session.getTransaction();
        User user = new User();
        user.setId(3);
        try {
            //开启事物
            transaction.begin();
            //执行操作
            session.delete(user);
            //提交事物
            transaction.commit();
        }catch (Exception e){
            //事物回滚
            transaction.rollback();
            System.out.println(e.getMessage());
        }
  1. 自动提交事物
<property name="hibernate.connection.autocommit">true</property>

3.6、session的API(方法)

  • save 保存
  • get 通过id查询,如果没有 null
  • load 通过id查询,如果没有抛出异常
  • update 更新
  • delete 删除
3.6.1、save(Object object);

向数据库插入数据,保存数据。

@Test
    public void test2(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.getTransaction();
        transaction.begin();
        session.save(new User("王麻子","wangmazi",(byte)30,'否'));
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
3.6.2、根据id获取数据
3.6.2.1、session.get(Class,Serelizble)获取数据;
@Test
    public void test2(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.getTransaction();
        transaction.begin();
        User user = session.load(User.class,2);
        System.out.println("*******"+user+"******");
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
3.6.2.2、session.load(Class,Serelizble)加载数据;
@Test
    public void test2(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.getTransaction();
        transaction.begin();
        User user = session.get(User.class,2);
        System.out.println("*******"+user+"******");
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
3.6.2.3、load与get方法的区别
  1. get与load方法都是根据id来获取数据。
  2. 当数据库没有id参数对应的数据时,get方法会返回null,而load方法会报错。
  3. get方法是直接去加载数据库,而load是懒加载,到用的时候才去加载数据库。他返回的是一个代理。此代理只有一个id属性,当我们要用到对象的其他属性时它才会去加载数据库。
  4. get方法是直接加载数据库
  5. load的设计是懒加载,用到时才去查询数据库
  6. load方法返回的是对象的一个代理
    在这里插入图片描述
  7. load执行原理图
    在这里插入图片描述
3.6.3、删除数据

删除数据用delete(Object);实际执行是是根据传入对象的id来匹配删除的。

3.6.3.1、第一种方式:先获取数据,然后删除。
@Test
    public void test5(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        User user = session.get(User.class, 2);
        Transaction transaction = session.getTransaction();
        try {
            //开启事物
            transaction.begin();
            //执行操作
            session.delete(user);
            //提交事物
            transaction.commit();
        }catch (Exception e){
            //事物回滚
            transaction.rollback();
            System.out.println(e.getMessage());
        }
        session.close();
        sessionFactory.close();
    }
3.6.3.2、第二种方式:直接创建一个带id的对象,然后删除。
@Test
    public void test4(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();

        //获取事物对象
        Transaction transaction = session.getTransaction();
        User user = new User();
        user.setId(3);
        try {
            //开启事物
            transaction.begin();
            //执行操作
            session.delete(user);
            //提交事物
            transaction.commit();
        }catch (Exception e){
            //事物回滚
            transaction.rollback();
            System.out.println(e.getMessage());
        }
        session.close();
        sessionFactory.close();
    }
3.6.3.3、注意:

删除操作时要手动提交事物,因为配置的字段提交事物对于删除操作不起作用。而两种删除操作,第一种因为要先执行查询操作,所有整体效率没有第二种高。因为删除操作是根据id匹配删除的,所有直接用第二种会更好。

3.6.4、更新数据
3.6.4.1、方式一:先获取数据,然后直接调用对象属性的setter方法修改数据,然后直接提交事物,会自动更新数据。但是如果是修改了对象id时会在执行完查询后报错,如果是没有手动提交事物,则不执行更新操作,只执行查询操作。如果是自行创建对象,则没有任何操作。
    @Test
    public void test7(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.getTransaction();
        transaction.begin();
        User user = session.get(User.class, 1);
        user.setName("孙七");
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
3.6.4.2、方式二:先获取数据,然后直接调用对象属性的setter方法修改数据,然后调用session.update(Object)方法,提交事物后修改数据。如果修改了id属性,则执行完查询后报错,效果同上,如果没有手动提交事物,则不执行更新操作,效果同上。如果没有先获取数据,而是自行创建数据,此时如果创建的对象在数据库没有id与之对应的数据,则会报错,提示没有对应的数据可以修改,如果有id对应的数据,则数据库设置不能为空的字段要全部赋值,否则会报错提示无法执行操作,因为字段不能为空。
    @Test
    public void test7(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.getTransaction();
        transaction.begin();
        User user = session.get(User.class, 1);
        user.setName("赵六");
        session.update(user);
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
3.6.4.2、方式三:先获取数据,然后直接调用对象属性的setter方法修改数据,然后调用session.save()方法。如果只是修改了id以外的字段,则调用save方法后自动提交事物,则同样执行数据更新操作。如果不手动提交事物,则只是查询操作,其他不作任何操作。如果同时修改了id字段,此时不做事物提交则只做查询操作,如果手动提交事物则报错。如果单纯的创建对象,然后调用save方法则就是单纯的插入操作。
    @Test
    public void test8(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.getTransaction();
        User user = session.get(User.class, 1);
        user.setName("张三");
        user.setId(2);
        user.setPass("ddd");
        user.setAge((byte)12);
        user.setType('否');
        transaction.begin();
        session.save(user);
        transaction.commit();
        session.close();
        sessionFactory.close();

    }
3.6.4.2、方式四:先获取数据,然后修改除id外的字段,然后调用saveOrUpdate()方法。先不手动提交事物,则除了查询外不做其他操作。如果手动提交事物,则做更新操作。如果修改了id字段,则在不做事物提交的话除了查询没有其他操作,如果手动提交事务。则或报错。如果是创建对象,赋值时如果有id,则会根据id去更新,手动提交事物更新成功,如果没有找到id对应的数据会报错。如果不提交事物,则不做任何操作。如果创建的对象没有id属性,则无论是否手动提交事物都会进行直接指向插入操作。
    @Test
    public void test8(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.getTransaction();
        User user = new User();
        //User user = session.get(User.class, 1);
        user.setName("李四");
        user.setPass("lisi");
        user.setAge((byte)20);
        user.setType('否');
        //transaction.begin();
        session.saveOrUpdate(user);
        //transaction.commit();
        session.close();
        sessionFactory.close();

    }
3.6.5、query使用hql查询
3.6.5.1、概念:

sql是结构化查询语言,针对数据库进行操作,而hql是面向对象的思想,与sql不同。其中查询是不用写select关键字,写查询数据源时写的是类名而不是表名。

  • HQL:Hibernate Query Language的缩写,就是Hibernate的查询语言
    面向对象查询语言,最终底层要转成面向数据库查询语言
    SQL:直接面向数据库查询语言
  • Query:用于查询的对象,可以设置查询条件个分页查询。
  • 在这里插入图片描述
3.6.5.2、注意:
  1. idea在写hql时候会遇到编译错误:can’t resolve symbol XXX。使用快捷键ctrl+alt+s进入设置界面,按红色矩形框操作,找到JPA issues下面的Query language check将其取消勾选,或者像我一样改为Warning。
  2. 在hibernate4.1之后对hql做了更改,所有在做query查询时写hql语句要注意hibernate的版本。4.1之后的占位符要符号JPA-style格式。也就是占位符后面要跟上坐标值,此坐标值可以随意,赋值时对应即可。
  3. hql语句是面向对象的,书写格式如:from User Where name=?0 and pass=?1,在hql语句中写的是类名跟类的属性,不是表名跟字段。另外就是占位符后面的坐标值,在4.1之后不写会报错。
  4. 如果用sql的格式如select nam,pass,age,type from User where nam=?0 and pass=?1替换掉hql语句,则可以执行正常的查询,但是结果是object格式,不能与entity对应,如果强转会报错。
3.6.5.3、查询整个表(返回多条结果用list方法)
    @Test
    public void test10(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        String hql = "from User";
        Query query = session.createQuery(hql);
        List<User> list= query.list();
        list.forEach(e-> System.out.println(e));
    }
3.6.5.3、带条件的查询(返回一条数据用uniqueResult方法)
  1. 需要注意的是上面第三点
    @Test
    public void test9(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        String hql = "from User where name=?0 and pass=?1";
        Query query = session.createQuery(hql);
        query.setParameter(0,"李四");
        query.setParameter(1,"lisi");
        User user = (User) query.uniqueResult();
        System.out.println(user);
    }
  1. 占位符书写麻烦可以采用取别名的方式
    @Test
    public void test11(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        String hql = "from User where name=:name and pass=:pass";
        Query query = session.createQuery(hql);
        query.setParameter("name","李四");
        query.setParameter("pass","lisi");
        User user = (User) query.uniqueResult();
        System.out.println(user);
    }
  1. 在createQuery中使用sql格式的hql,需要注意的是第四点
    @Test
    public void test9(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        String sql = "select nam,pass,age,type from User where nam=?0 and pass=?1";
        String hql = "from User where name=?1 and pass=?2";
        Object o = session.createQuery(hql).setParameter(1, "李四").setParameter(2, "lisi").uniqueResult();
        System.out.println(o);
        /*query.setParameter(0,"李四");
        query.setParameter(1,"lisi");
        User user = (User) query.uniqueResult();*/
        //System.out.println(user);
    }
3.6.5.3、分页查询
    @Test
    public void test12(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        String hql = "from User";
        Query query = session.createQuery(hql);
        query.setFirstResult(3);
        query.setMaxResults(3);
        List<User> list = query.list();
        list.forEach(System.out::println);
    }

类似limit3,3,两个参数是通过setFirstResult(3)和setMaxResults(3)实现的。

3.6.6、Criteria查询

QBC(query by criteria)。hibernate提供纯面向对象查询语言,提供直接使用po对象操作。

  • 案例代码:
  • 在这里插入图片描述
  • 概念:
  1. PO:persistent object ,用于与数据库交互数据。–dao层 (JavaBean + hbm )

  2. BO:Business object 业务数据对象。–service层

  3. VO:Value Object 值对象。–web层

  4. 普通条件查询。等值查询

    @Test
    public void test13(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Criteria criteria = session.createCriteria(User.class);
        criteria.add(Restrictions.eq("name","张三"));
        criteria.add(Restrictions.eq("pass","zhangsan"));
        User user = (User) criteria.uniqueResult();
        System.out.println(user);
    }
  1. 一般条件查询(大于小于)
    @Test
    public void test15(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Criteria criteria = session.createCriteria(User.class);
        //gt是指大于 ge是指大于等于
        criteria.add(Restrictions.gt("age",(byte)30));
        //lt是指小于 le是指小于等于
        criteria.add(Restrictions.lt("age",(byte)30));
        criteria.list().forEach(System.out::println);
    }
  1. 模糊查询
    @Test
    public void test14(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Criteria criteria = session.createCriteria(User.class);
        criteria.add(Restrictions.like("pass","%a%"));
        List<User> list = criteria.list();
        for (User user : list) {
            System.out.println(user);
        }
    }
3.6.7、sqlQuery

sqlQuery是原生SQL查询。并不是所有的SQL都可以用hql来代替

  • 案例代码
  • 在这里插入图片描述
    @Test
    public void test16(){
        Configuration cfg = new Configuration().configure();
        cfg.addClass(User.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        String sql = "select * from user";
        SQLQuery sqlQuery = session.createSQLQuery(sql);
        //sqlQuery.setParameter(1,"张三");
        //sqlQuery.setParameter(2,"zhangsan");
        List<Object[]> list = sqlQuery.list();
        list.forEach(e -> {
            for (Object o : e) {
                System.out.println(o);
            }
            System.out.println("=========");
        });
    }

使用SQLQuery查询到的结果是每行数据的结果集。返回一个集合,集合中存储的是数组对象。

3.6.7、封装获取session的工具
/**
 * @Auther: 邪灵
 * @Date: 2019/11/22 14:00
 * @Description: hibernate工具
 * @Since: 1.0
 */
public class HibernateUtil {
    private static SessionFactory sessionFactory;
    static {
        //获取核心 配置对象
        Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
        //创建会话工厂
        sessionFactory = configuration.buildSessionFactory();
        //设置程序关闭监听
        Runtime.getRuntime().addShutdownHook(new Thread(){
            @Override
            public void run() {
                sessionFactory.close();
                System.out.println("程序关闭");
            }
        });
    }
    public static Session getSession(){
        return sessionFactory.openSession();
    }
    public static Session getCurrentSession(){
        return sessionFactory.getCurrentSession();
    }
}

3.7、配置文件详解

3.7.1、hibernate.cfg.xml说解

掌握各个配置的作用
在这里插入图片描述
在这里插入图片描述

3.7.2、hbm.xml映射文件解说

实体类的编写规则

  • 我们在使用Hibernate时,书写了一个User类,这个类我们称为JavaBean
  • JavaBean可以简单的理解成提供私有属性,并提供私有属性的get/set方法
  • POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans
  • 我们也称为模型,在Hibernate中,又称这种类为实体,因为是与表关联的
    编写规则
  1. 提供一个无参数 public访问控制符的构造器
  2. 提供一个标识属性 ,映射数据表主键字段,提供id
  3. 所有属性提供public访问控制符的 set get 方法(javaBean)
  4. 标识属性应尽量使用基本数据类型的包装类
  5. 不要用final修饰实体 (将无法生成代理对象进行优化)

持久化对象的唯一表示OID

  • Java按地址区分同一个类的不同对象.
  • 关系数据库用主键区分同一条记录
  • Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系结论: 对象的OID和数据库的表的主键对应。
  • 为保证OID的唯一性,应该让Hibernate来为OID赋值
    区分自然主键和代理主键
  • 主键需要具备: 不为空/不能重复/不能改变
  • 自然主键: 在业务中,某个属性符合主键的三个要求.那么该属性可以作为主键列.【登录名可以是自然主键】
  • 代理主键: 在业务中,不存符合以上3个条件的属性,那么就增加一个没有意义的列.作为主键.
    基本数据与包装类型
  • 基本数据类型和包装类型对应hibernate的映射类型相同
  • 基本类型无法表达null、数字类型的默认值为0。
  • 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。
    SQL、Hibernate和对象类型对应
java数据类型hibernate数据类型标准SQL数据类型
byte、java.lang.BytebyteTINYINT
short、java.lang.ShortshortSMALLINT
int、java.lang.IntegerintegerINGEGER
long、java.lang.LonglongBIGINT
float、java.lang.FloatfloatFLOAT
double、java.lang.DoubledoubleDOUBLE
java.math.BigDecimalbig_decimalNUMERIC
char、java.lang.CharactercharacterCHAR(1)
boolean、java.lang.BooleanbooleanBIT
java.lang.StringstringVARCHAR
boolean、java.lang.Booleanyes_noCHAR(1)(‘Y’或’N’)
boolean、java.lang.Booleantrue_falseCHAR(1)(‘Y’或’N’)
java.util.Date、java.sql.Date dateDATE
java.util.Date、java.sql.Time timeTIME
java.util.Date、java.sql.Timestamptimestamp TIMESTAMP
java.util.CalendarcalendarTIMESTAMP
java.util.Calendarcalendar_date DATE
byte[] binaryVARBINARY、BLOB
java.lang.String textCLOB
java.io.SerializableserializableVARBINARY、BLOB
java.sql.ClobclobCLOB
java.sql.BlobblobBLOB
java.lang.ClassclassVARCHAR
java.util.LocalelocaleVARCHAR
java.util.TimeZonetimezoneVARCHAR
java.util.CurrencycurrencyVARCHAR

主键生成策略

<id name="uid" column="id">
   <!-- generator:id的生成策略
      increment:也会自动增长id,但是它的这种增长是自己Hibernate实现
                 执行select max(id) 查询,这种会有线程并发问题
      sequence:一般在oracle数据库才用
      hilo:hibernate自己实现的id规则【不用,不用学】
      native:【经常常用】
          如果是mysql数据库,id会自动增长
          如果是oracle数据库,会自动增长,sequence
      uuid:【经常常用】一个长字符串,需要把模型的id改成字符串
             保存的时候,不用自己设置ID,hibernate会设置id
      assigned:【经常常用】要手动设置id属性
    -->
   <generator class="assigned"></generator>
</id>

普通属性

  • class标签的dynamic-insert=“true” 是否动态生成插入语句,
  • 【如果属性字段为空,就不会有些字段的插入语句】
  • class标签的dynamic-update=“true” 与insert类似
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述
    type的使用
    在这里插入图片描述
    在这里插入图片描述

3.8、Hibernate实体的状态

3.8.1、状态介绍

  • 实体entity有三种状态,瞬时状态,持久状态,脱管状态
  • 瞬时状态:transient,session没有缓存,数据库没有记录,oid没有值。
  • 持久状态:persistent,session有缓存,数据库有记录,oid有值。
  • 脱管状态:detached,session没有缓存,数据库有记录,oid有值。
3.8.2、瞬时 转 持久
  • 新创建的一个对象,经过save,或者savaOrUpdate调用后,会变成持久状态
    在这里插入图片描述
3.8.3、持久 转 脱管
  • load,get返回的对象是持久状态的,当session关闭或者清除后,对象变成脱管状态
    在这里插入图片描述
3.8.4、总结状态的转换过程
  • 查询操作:get、load、createQuery、createCriteria 等 获得都是持久态
  • 瞬时状态执行save、update、saveOrUpdate之后变成持久状态
  • 持久态 转换 脱管态
  1. session.close () 关闭
  2. session.clear() 清除所有
  3. session.evict(obj) 清除指定的PO对象

4、一级缓存

4.1、概念

一级缓存:又称为session级别的缓存。当获得一次会话(session),hibernate在session中创建多个集合(map),用于存放操作数据(PO对象),为程序优化服务,如果之后需要相应的数据,hibernate优先从session缓存中获取,如果有就使用;如果没有再查询数据库。当session关闭时,一级缓存销毁。

4.2、证明一级缓存

在这里插入图片描述

4.3、移除缓存

在这里插入图片描述

4.4、一级缓存快照

快照:与一级缓存存放位置是一样,对一级缓存数据备份。保证数据库的数据与 一级缓存的数据必须一致。如果一级缓存修改了,在执行commit提交时,将自动刷新一级缓存,执行update语句,将一级缓存的数据更新到数据库
在这里插入图片描述
在这里插入图片描述

4.5、快照演示(一级缓存刷新)

在这里插入图片描述

4.6、一级缓存的细节

  • HQL的结果会进行一级缓存,SQL的结果不会添加到一级缓存
    在这里插入图片描述在这里插入图片描述

5、其他API

5.1、save和persist方法的区别

save方法:瞬时态 转换 持久态,会初始化OID

  1. 执行save方法,立即触发insert语句,从数据库获得主键的值(OID值)
  2. 执行save方法前,设置OID将忽略。
  3. 如果执行查询,session缓存移除了,在执行save方法,将执行insert
    在这里插入图片描述
    persist方法:瞬时态 转换 持久态
  • persist保存的对象,在保存前,不能设置id,否则会报错
  • save和persist都是持久化对象的作用
  • save 因为需要返回一个主键值,因此会立即执行 insert 语句,而 persist 在事务外部调用时则不会立即执行 insert 语句,在事务内调用还是会立即执行 insert 语句的。
    在这里插入图片描述
    update方法
    在这里插入图片描述
    saveOrUpdate方法
    判断是否有OID,如果没有OID,将执行insert语句,如果有OID,将执行update语句。
    在这里插入图片描述
    Delete方法

6、Hibernate的多表关联关系映射

6.1、回顾多表关系

  • 表之间关系存在3钟:一对多、多对多、一对一。(回顾)
    在这里插入图片描述
  • 多对多关系:课程与学生
  • 一对多关系:学生与成绩
  • 一对一关系:学生与身份证
  1. 一对多:主表的主键 与 从表外键 形成 主外键关系
  2. 多对多:提供中间表(从表),提供两个字段(外键)分别对应两个主表。
  3. 一对一:主外键关系

6.2、案例:一对多、多对一

  • 客户和订单的关系是一对多的关系,订单和客户的关系是多对一的关系
    实体类的编写
    注意:set集合一定要定义的时候初始化对象,需要提供属性的get/set方法

在这里插入图片描述
映射文件的编写

  • Customer.hbm.xml
<hibernate-mapping package="com.gyf.hibernate.domain">
	
	<class name="Customer" table="t_customer">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<property name="name" length="20"></property>

		<!-- 一个客户有多个定单,Hibernate可以双向描述一对多的关系
			set中 name写的是实例的属性
		  -->
		<set name="orders">
			<!-- column指的是Order表中的外键  -->
						<key column="customer_id"></key>
			<one-to-many class="Order"/>
		</set>
	</class>
</hibernate-mapping>

  • Order.hbm.xml
<hibernate-mapping package="com.gyf.hibernate.domain">
	
	<class name="Order" table="t_order">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		
		<!-- 定单名称 -->
		<property name="name"></property>

		<!-- 多个定单对应一个客户,Hibernate可以双向描述一对多的关系
			set中 name写的是实例的属性
		  -->
		<many-to-one name="customer" class="Customer" column="customer_id"></many-to-one>
	</class>
</hibernate-mapping>

单元测试

	@Test
	public void test1(){
		
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		
		//客户
		Customer customer = new Customer();
		customer.setName("gyf");
		
		//定单
		Order order1 = new Order();
		order1.setName("iphone8");
		
		Order order2 = new Order();
				order2.setName("iphonex");
		
		//维护客户与定单的关系
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);
		
		//维护定单与客户的关系
		order1.setCustomer(customer);
		order2.setCustomer(customer);
		
		session.save(customer);//执行三条insert sql语句
		session.save(order1);//执行一条update sql语句,维护外键关系
		session.save(order2);//执行一条update sql语句,维护外键关系
		
		
		
		session.getTransaction().commit();
		session.close();
		
	}

设置外键维护的方式

  • 修改Customer的配置文件,添加一个inverse选项
  • inverse是hibernate双向关系中的基本概念。inverse的真正作用就是指定由哪一方来维护之间的关联关系。当一方中指定了“inverse=false”(默认),那么那一方就有责任负责之间的关联关系。
    在这里插入图片描述
    查询一对多和删除
    一对多的查询,会执行两条SQL语句
    在这里插入图片描述

6.3、cascade级联

save-update
级联保存,级联修改,保存A(客户)时,同时保存B(订单)
delete
级联删除,删除A时,同时删除B。
在这里插入图片描述
delete-orphan孤儿删除
孤儿删除,解除关系,同时将B删除,A存在的。
在这里插入图片描述在这里插入图片描述
级联组合:
如果需要配置多项,使用逗号分隔。
all : save-update 和 delete 整合
all-delete-orphan : 三个整合

6.4、Hibernate实体状态回顾

在这里插入图片描述

7、Hibernate的多表关联关系映射

7.1、多对多的关联关系映射

  • 目标:掌握如何多表关联的映射进行配置
  • 以学生和课程为例,一个学生可以对应多个课程,多个学生可以对应一个课程
7.1.1、学生和课程的JavaBean(entity,pojo,model)

在这里插入图片描述

7.1.2、学生和课程表的hbm.xml映射
  • Student.hbm.xml
    在这里插入图片描述
  • Course.hbm.xml
    在这里插入图片描述

7.2、多对多的测试

7.2.1、自动生成三张表
	public void test1(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		session.getTransaction().commit();
				session.close();
	}
  • 在这里插入图片描述
7.2.2保存一个学生
  • 注意保存前的外键维护和级联是如何配置
  • 一般操作多的一方选择级联,这里学生操作比较多
@Test
public void test1(){
   /**
        * 保存多对多数据
    */
   Session session = HibernateUtils.openSession();

   session.getTransaction().begin();

   //1.创建2个学生
   Student stu1 = new Student("特朗普");
   Student stu2 = new Student("普京");

   //2.创建2个课程
   Course c1 = new Course("维护世界和平");
   Course c2 = new Course("外贸");

   //3.绑定课程到学生
   stu1.getCourses().add(c1);
   stu1.getCourses().add(c2);

   stu2.getCourses().add(c1);
   stu2.getCourses().add(c2);

   //4.保存
   /**
    * 保存的注意事项
    * 1.配置级联保存,只保存学生对象
    *  插入2个学生,插入2两课程,中间4条,8条sql
    * 2.如果在Student配置inverse="true",由Course来维护外键关系,中间表没数据
    * 3.默认Student配置inverse="false",由Student来维护外键关系,中间表有数据
    * 4.多对多,inverse不能两边都为true,如果两边都为true,不管保存哪个对象,中间表都没有数据
    */
   /*session.save(stu1);
   session.save(stu2);*/

   //课程拥有有学生
   c1.getStudents().add(stu1);
   c1.getStudents().add(stu2);

   c2.getStudents().add(stu1);
   c2.getStudents().add(stu2);

   session.save(c1);
   session.save(c2);


   session.getTransaction().commit();
   session.close();

}

7.3、加载策略

7.3.1、类级别的加载策略
  • get:立即检索。get方法一执行,立即查询所有字段的数据。
  • load:延迟检索。默认情况,load方法执行后,如果只使用OID的值不进行查询,如果要使用其他属性值才查询
  • 如果在类级别上配置lazy为true,那load方法就会即时加载,否则为延时加载
    在这里插入图片描述在这里插入图片描述
7.3.2、关联级别的加载策略
  • 关联级别的集合加载的策略是默认是懒加载
  • 可以设置为即时加载,如图,即加载学生时,学生所属的课程也会加载进来
    在这里插入图片描述在这里插入图片描述
7.3.3fecth

Fecth:拿取,获取数据
fecth:是指查询集合的sql方式
select:默认的,普通select查询语句
join:表连接语句查询
subselect:使用子查询

在这里插入图片描述
fetch:select

  • set集合默认的sql查询方式就是fectch=select,一个普通的select查询语句
    fetch:join
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    fetch:subselect
    【只能用于多对多,一对多】
    在这里插入图片描述在这里插入图片描述
7.3.4、多对一的加载策略
  • 这里以Customer和Order多例来讲
  • 多对一标签<many-to-one fetch="" lazy="">
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
7.3.5、批量加载
  • set标签可以配置一个batch-size=“2”,表示每次可以加载两条数据
    在这里插入图片描述在这里插入图片描述
7.3.6检索策略
检索策略优点缺点优先考虑使用的场合
立即检索,即时加载对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象(1)select语句多(2)浪费内存空间(1)类级别(2)应用程序需要立即访问的对象(3)使用了二级缓存
延迟检索,懒加载的意思由应用程序决定需要加载哪些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间。应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。(1)一对多或者多对多关联(2)应用程序不需要立即访问或者根本不会访问的对象
表连接检索(1)对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象。(2)使用了外连接,select语句少(1)可能会加载应用程序不需要访问的对象,浪费内存。(2)复杂的数据库表连接也会影响检索性能。(1)多对一或一对一关联(2)需要立即访问的对象(3)数据库有良好的表连接性能。

8、HQL查询

8.1、HQL简介

  • HQL(Hibernate Query Language) 描写对象操作的一种查询语言,Hibernate特有
  • HQL的语法与SQL基本一致,不同的是HQL是面向对象的查询,查询的是对象 和对象中的属性
  • HQL的关键字不区分大小写,但类名和属性区分大小写
  • 语法示例
SELECT 别名/属性名/表达式
FROM 实体 AS 别名
WHERE 过滤条件
GROUP BY 分组条件
HAVING 分组后的结果的过滤条件
ORDER BY 排序条件

8.2、案例1:查询所有客户

在这里插入图片描述

8.3 案例2:选择查询

在这里插入图片描述

8.4 案例3:投影查询

在这里插入图片描述在这里插入图片描述

8.5 案例4:排序

在这里插入图片描述

8.6 案例5:分页

Query query = session.createQuery("from Customer");
// *** pageNum 当前页(之前的 pageCode)
query.setFirstResult(0);
// * 每页显示个数 , pageSize
query.setMaxResults(2);

8.7 案例6:聚合函数和分组查询

在这里插入图片描述

8.8 案例7:连接查询

INNER JOIN: 在表中存在至少一个匹配时,INNER JOIN 关键字返回行。
LEFT OUTER JOIN: 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行
RIGHT OUTER JOIN:关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。
在这里插入图片描述

8.8.1 交叉连接,等效笛卡尔积

在这里插入图片描述

8.8.2 隐式内连接,等效SQL隐式内连接

在这里插入图片描述

8.8.3 内连接,等效SQL内连接

在这里插入图片描述

8.8.4 迫切内连接,hibernate底层使用 内连接

在这里插入图片描述

8.8.5 左外连接,等效SQL左外连接

在这里插入图片描述

8.8.6 迫切左外连接,hibernate底层使用 左外连接

在这里插入图片描述

8.8.7 右外连接(迫切),等效SQL右外连接

在这里插入图片描述

8.9 案例8:命名查询

  • HQL语句写在java文件里,有时候不灵活,如果要修改语句,要重新编译项目打包
  • 我们可以在hbm.xml中命名查询语句,然后java中从hbm.xml取出hql语句,这样,以后的开发,可以直接找hbm.xml进行配置
    Hbm.xml
    在这里插入图片描述在这里插入图片描述

9、QBC查询

9.1 简介

QBC:Query By Criteria 条件查询,面向对象的查询的方式

9.2 简单查询

在这里插入图片描述

9.3 分页

在这里插入图片描述

9.4 排序

在这里插入图片描述

9.5 条件查询

在这里插入图片描述

9.6 离线查询

DetachedCriteria 离线查询对象,不需要使用Session就可以拼凑查询条件。一般使用在web层或service层拼凑。将此对象传递给dao层,此时将与session进行绑定执行查询。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值