Hibernate 目录
一:Hibernate的简介
Hibernate核心
Hibernate 基本原理
1)Hibernate初始化,读取并解析配置文件
2)读取并解析映射信息,创建SessionFactory
3)打开SESSION
4)创建事物Transaction
5)持久化操作
6)提交事务
7)关闭Session
8)关闭SessionFactory
Hibernate的模拟实现原理
Hibernatehelloworld
hibernate.cfg.xml<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/b2c_v2_alpha_3c</property> <property name="connection.username">root</property> <property name="connection.password">123456</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Enable Hibernate's automatic session context management --> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!-- 写update只是更新操作,也可以写create, 这样写create的话程序运行的时候就会把数据库里的内容全部删除并且重新创建, 当然,前提是数据库必须存在,因为hibernate只会创建表结构, 不会创建数据库,如果指定的数据库不存在,hibernate则会抛出异常 --> <property name="hbm2ddl.auto">update</property> <!-- Drop and re-create the database schema on startup --> <!-- <mapping resource="com/hibernate/model/GroupClass.hbm.xml"/> --> <mapping class="com.hibernate.model.Ith_Admin_Log"/> </session-factory> </hibernate-configuration>
package com.hibernate.model; public class GroupClass { private String class_id ; private String name; private String sort; public String getClass_id() { return class_id; } public void setClass_id(String class_id) { this.class_id = class_id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSort() { return sort; } public void setSort(String sort) { this.sort = sort; } }
GroupClass.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hibernate.model.GroupClass" table="group_class"> <id name="class_id" column="class_id"/> <property name="name" /> <property name="sort" /> </class> </hibernate-mapping>
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import com.hibernate.model.GroupClass; public class Demo { public static void main(String []args) { GroupClass gc = new GroupClass(); gc.setClass_id(String.valueOf(System.currentTimeMillis())); gc.setName("zhudansheng"); gc.setSort("3"); //加载配置文件 Configuration config = new Configuration(); //读取配置文件建立Session工厂 SessionFactory sf = config.configure().buildSessionFactory(); //建立连接 Session session = sf.openSession(); //开始事物 hibernate 操作数据库都使用事物机制 session.beginTransaction(); //操作SQL session.save(gc); //获取事物进行操作数据库,提交 session.getTransaction().commit(); //关闭事物 session.close(); sf.close(); } }
package com.hibernate.model; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.*; //@使用注解 annotation @Entity @Table(name="admin_log") public class Ith_Admin_Log { private String log_id; private String user_id; private String log_info; private String ip; private String add_time; private String sex; private Date add_date; @Id public String getLog_id() { return log_id; } public void setLog_id(String log_id) { this.log_id = log_id; } @Column(name="add_user") public String getUser_id() { return user_id; } public void setUser_id(String user_id) { this.user_id = user_id; } public String getLog_info() { return log_info; } public void setLog_info(String log_info) { this.log_info = log_info; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getAdd_time() { return add_time; } public void setAdd_time(String add_time) { this.add_time = add_time; } //@Transient public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Temporal(TemporalType.DATE) public Date getAdd_date() { return add_date; } public void setAdd_date(Date add_date) { this.add_date = add_date; } }
import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import com.hibernate.model.Ith_Admin_Log; public class AnnotationnDemo { public static void main(String []args) { Ith_Admin_Log adminLog = new Ith_Admin_Log(); adminLog.setLog_id(String.valueOf(System.currentTimeMillis())); adminLog.setUser_id("2222222222222"); adminLog.setLog_info("测试建立数据库的的连接annotation "); adminLog.setIp("222.33.22.3"); adminLog.setAdd_time("2011-2-20"); adminLog.setSex("男"); adminLog.setAdd_date(new Date()); Configuration cfg = new AnnotationConfiguration(); SessionFactory sf =cfg.configure().buildSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); session.save(adminLog); session.getTransaction().commit(); session.close(); sf.close(); } }
Hibernate目前实现由两种方式:XML,ANNOTATION
1)XML:通过使用XML的配置关联数据库,操作数据库表
2)注解(Annotation):注解使用了JPA的接口标准,其他都是JPA的实现二:
流行ORM框架简介
技术日新月异,今天非常流行的技术,明天或将淘汰,所以我建议学习思想,思路,原理。练习内功才是上策。
因为有了Hibernate的支持,使得JavaEE应用的OOA(面向对象分析)、OOD(面向对象设计)和OOP(面向对象编程)三个过程一脉相承,成为一个整体.
(1)EnitiyEJB:EnitiyEJB实际上也是一种ORM技术,这是一直备受争议的组件技术。事实上,EJB为JavaEE的蓬勃发展赢得了极高的声誉,EJB作为一种重量级、高花费的ORM技术具有不可比拟的优势。就其他架构设计来讲,依然非常优秀。即使现在十分流行的轻量级JavaEE架构,其实质是对经典JavaEE架构的模仿——虽然存在些许的改进。EJB3.1
也采取了低侵入式的设计,增加了Annotation,也具有极大的吸引力。
(2)Hibernate:目前最流行的开源ORM框架,已经被选作JBoss的持久层解决方案。整个HIbernate项目也一并投入了Jboss的怀抱,而JBoss又加入了RedHat组织,所以现在Hibernate属于RedHat的一部分。Hibernate灵巧的设计、优秀的性能,还有其丰富的文档都是其风靡全球的重要因素。
(3)iBatis:Apache软件基金组织的子项目。与其称它为一种ORM框架,不如称它为一中“SQLMapping”框架。曾经在J2EE的开发中扮演非常重要的角色,但因为不支持存粹的面向对象操作,因此现在逐渐地被取代。但是在一些公司,依然占有一席之地,特别是一些对数据访问特别灵活的地方,iBatis更加的灵活,它允许开发人员直接编写SQL语句。
(4)TopLink:Oracle公司的产品,作为一个遵循OTN协议的商业产品,TopLink在开发过程中可以自由地下载和使用,但是一旦作为商业产品被使用,则需要收取费用。由于这一点,TopLink的市场占有率不高。
(5)OBJ:Apache软件基金组织的子项目。另一个开源的ORM框架,可以说是Apache作为iBatis之后的取代产品,也是非常优秀的O/R Mapping框架,但是由于Hibernate 的广芒太盛,所以并未有广泛的使用,而且由于OJB的开发文档不是很多,这也影响了OJB的流行。目前流行的编程语言,如Java、C# 等,它们都是面向对象的编程语言,而目前主流的数据库产品例如Oracle、DB2等,依然是关系型数据库。编程语言和底层数据库发展的不协调,催生出了ORM框架。ORM框架可以作为面向对象语言和关系型数据库之间的桥梁。
1. 对象/关系数据库映射(ORM)
ORM的全称是Object/Relation Mapping,对象/关系数据库映射。ORM可以理解成一种规范,它概述了这类框架的基本特征:完成面向对象编程语言和关系型数据库的映射。当ORM框架完成映射后,它既可利用面向对象程序设计语言的简单易用性,又可以利用关系型数据库的技术优势。因此,我们可以把ORM框架当成是应用程序和数据库的桥梁。
当我们使用一种面向对象程序设计语言来进行应用开发时,从项目开始起就采用的是面对对象分析、面向对象设计、面向对象编程,但到了持久层数据库访问时,又必须重返关系型数库的访问方式,这是一种糟糕的感觉。于是我们需要一种工具,它可以把关系型数据库包装成一个面向对象的模型,这个工具就是ORM框架。
ORM是面向对象程序设计语言与关系型数据库发展不同步时的中间解决方案。随着面向对象数据库的发展 ,其理论逐步完善,最终会取代关系型数据库。只不过这个过程不会一蹴而就,ORM框架在此期间仍将蓬勃发展。但是随着面对对象数据库的出现,ORM工具会自动的消亡。
对时下流行的编程语言而言,面向对象程序设计语言代表了目前程序设计语言的主流和趋势,具备了非常多的优势。比如:
(1)面向对象的建模、操作
(2)多态、继承
(3)摒弃难以理解的过程
(4)简单易用易理解
但数据库的发展并未与程序设计语言同步,而且关系数据库的某些优势也是面向对象的语言无法比拟的。比如:
(1)大量数据的查找和排序
(2)集合数据连接操作、映射
(3)数据库访问的并发、事务
(4)数据库的约束和隔离
当我们采用ORM框架之后,应用程序不再直接访问底层的数据库,而是以面向对象的方式来操作持久化对象(例如创建、修改、删除等),而ORM框架则将这些面向对象操作转换成底层的SQL操作。
正如上图所示ORM工具的唯一作用就是把持久化对象的操作转换成对数据库的操作,从此程序员可以以面向对象的方式操作持久化对象,而ORM框架则负责转换成对应的SQL(结构化查询语言)操作。
2. 基本映射方式
ORM工具提供了持久化类和数据表之间的映射关系 ,通过这种关系的映射过渡,我们可以很方便地通过持久化类对数据表进行操作。实际上,所有ORM工具大致上都遵循相同的映射思路。
ORM基本映射有如下这几条映射关系:
(1) 数据表映射类 :
持久化类被映射到一个数据表。当我们使用这个持久化类来创建实例、修改属性、删除实例时,系统自动会转换为对这个表进行CRUD操作,下图显示了这种映射关系。
正如上图所示,受ORM管理的持久化类(就是一个普通的Java类)对应一个数据表,只要我们对这个持久化类进行操作,系统可以转换成对对应数据表的操作。
(2) 数据表的行映射对象(即实例):
持久化类会生成很多的实例,每个实例就对应数据表中的一行记录。当我们在应用中修改持久化类的某个实例时,ORM工具将会转换成对对应数据表中的特定行的操作。每个持久化对象对应数据表的一行记录。如下图所示:
(3) 数据表的列(字段)映射对象的属性:
当我们在应用中修改某个持久化对象的制定属性时(持久化数据映射到数据行),ORM将会转换成对对应表中指定数据行、指定列的操作。数据表列被映射到对象属性的示意图如下表示:
基于这些基本的映射方式,ORM工具可完成对对象模型和关系模型之间的相互映射。由此可见,在ORM框架中,对象持久化是一种中间媒介,应用程序只需要操作持久化对象,ORM框架则负责将这种操作转换为底层数据库操作——这种转换对开发者来说透明,无需开发者关心,从而将开发者从关系模型中解放出来,使得开发者能够以面向对象的思维操作关系型数据库。
三:准备阶段
<!--EndFragment-->
1)hbm2ddl的使用update,create,delete等等
<property name="hbm2ddl.auto">update</property>
update:在加载hibernate的时候,更新数据库的数据
create:重新创建数据库表结构,这样导致的原因是数据库表数据丢失
create-drop:加载hibernate时创建,退出是删除表结构
validate:加载hibernate的时候,验证数据库表结构
总结:请慎重使用此参数,没必要就不要随便用;如果发现数据库表丢失,请检查hibernate.hbm2ddl.auto的配置
2)分析业务(业务逻辑,业务流程),再建立表(建立表使用powerdesigner),最后建立类(ORM中的O)
此处是高级程序员向产品经理或项目经理过渡的过程。
3)搭建log4j日志查看日志信息:使用slf4j作为接口标准。
SLF4J(Simple Logging Facade for Java)是一个通用的日志框架接口标准。 实现SLF4J的接口有很多,但是目前兼容最好的是LOG4J。
下载SLF4J:http://www.slf4j.org/download.html
下载LOG4J:http://logging.apache.org/log4j/1.2/download.html
1. slf4j-api-1.5.11.jar
2.slf4j-log4j12-1.5.11.jar
3.log4j-1.2.15.jar
4. log4j.properties
log4j.properties
log4j.rootLogger=DEBUG,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n
Log4j建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG
static Level DEBUG
DEBUG Level指出细粒度信息事件对调试应用程序是非常有帮助的。
static Level INFO
INFO level表明 消息在粗粒度级别上突出强调应用程序的运行过程。
static Level WARN
WARN level表明会出现潜在错误的情形。
static Level ERROR
ERROR level指出虽然发生错误事件,但仍然不影响系统的继续运行。
static Level FATAL
FATAL level指出每个严重的错误事件将会导致应用程序的退出。
org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)org.apache.log4j.HTMLLayout(HTML表格形式)
org.apache.log4j.SimpleLayout(简单格式的日志,只包括日志信息的级别和指定的信息字符串,如:DEBUG-Hello)
org.apache.log4j.TTCCLayout(日志的格式包括日志产生的时间、线程、类别等等信息)
org.apache.log4j.PatternLayout(灵活地自定义日志格式)
当使用org.apache.log4j.PatternLayout来自定义信息格式时,可以使用
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss}%p-%m%n来格式化信息
%c输出所属类的全名,可写为%c{Num},Num类名输出的范围如:"com.sun.aaa.classB",%C{2}将使日志输出输出范围为:aaa.classB
%d输出日志时间其格式为可指定格式如%d{HH:mm:ss}等
%l输出日志事件发生位置,包括类目名、发生线程,在代码中的行数
%n换行符
%m输出代码指定信息,如info(“message”),输出message
%p输出日志的优先级,即FATAL,ERROR等
%r输出从启动到显示该条日志信息所耗费的时间(毫秒数)
%t 输出产生该日志事件的线程名实例:
首先加入包:
Log4j-1.2.16.jar
Slf4j-api-1.6.4.jar
Slf4j-log4j12-1.6.4.jar
<!--EndFragment-->
Log4j.properties
#log4j.rootLogger=DEBUG,console #log4j.appender.console=org.apache.log4j.ConsoleAppender #log4j.appender.console.layout=org.apache.log4j.PatternLayout #log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n
log4j.rootLogger=DEBUG,LOGFILE log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.file=alllog log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} |
package com.hibernate.slf4j;
import org.slf4j.Logger; import org.slf4j.LoggerFactory;
public class TestSLF4JDemo { public static void main(String []args) { Logger logger =LoggerFactory.getLogger(TestSLF4JDemo.class); logger.debug("debug 级别"); logger.error("ERROR 级别"); logger.info("INF0 级别 {}", 1); logger.trace("TRACE 级别"); logger.warn("WARN 级别"); } }
|
4)搭建junit进行测试。
JUNIT是在程序员白盒测试的时候使用。
@BeforeClass 加载配置文件或实例化,
@Test 测试实例代码,
@AfterClass 关闭资源
实例:
导入包:junit-4.10.jar
package com.hibernate.slf4j;
import org.slf4j.Logger; import org.slf4j.LoggerFactory;
public class TestSLF4JDemo { public static void main(String []args) { Logger logger =LoggerFactory.getLogger(TestSLF4JDemo.class); logger.debug("debug 级别"); logger.error("ERROR 级别"); logger.info("INF0 级别 {}", 1); logger.trace("TRACE 级别"); logger.warn("WARN 级别"); }
public static void test() { Logger logger =LoggerFactory.getLogger(TestSLF4JDemo.class); logger.debug("debug 级别"); logger.error("ERROR 级别"); logger.info("INF0 级别 {}", 1); logger.trace("TRACE 级别"); logger.warn("WARN 级别"); } } |
package com.juit.test;
import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test;
import com.hibernate.slf4j.TestSLF4JDemo;
public class TestDemo {
@BeforeClass public static void BeforeClass() { System.out.println("========doBeforeClassdoBeforeClassdoBef======="); }
@Test public void Test() { System.out.println("=======doTestdoTestdoTestdoTestdoTest========"); TestSLF4JDemo.test(); }
@AfterClass public static void AfterClass() { System.out.println("========doAfterClassdoAfterClassdo======="); } }
|
<!--EndFragment-->
四:Hibernate的基础配置(重点)
注解细讲【主要是区别注解和XML】
注解:都需要位于javax.persitentice.*;可以使用@Entity
表名和类中定义的名称不同使用@Table(name="table_name")
字段名和表中的字段名不同使用@Column(name="xxx")
不需要持久化字段:@Transient(transient)透明的
注解使用日期可以使用@Temportal(TemportalType.DATE)
hibernateannotation字段映射位置,应该放在get上面
为什么不加属性上面。因为属性本身就是私有的,私有的本身就不需要别人调用。
查资料的能力(获取情报信息能力)和综合运用能力(体现在项目)