博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Hibernate复习笔记(2)——Hibernate 5.X的使用概述、示例与总结
阅读量:6670 次
发布时间:2019-06-25

本文共 26381 字,大约阅读时间需要 87 分钟。

hot3.png

Hibernate的更新有时让人觉得反复无常,当我们在Hibernate3习惯使用conf.buildSessionFactory();时,在Hibernate4中又推荐使用ServiceRegistry来创建:configuration.buildSessionFactory(serviceRegistry)原有的buildSessionFactory()方法被Deprecated;到了Hibernate5似乎又改了,真是随性,坑了主动更新的小白们。

这次复习博客系列就顺带着从入门到高级,按照Hibernate5的新特性整理一遍。

一张图回顾Hibernate使用的四大步骤:

153144_MfCW_1156339.png

Step 1.创建一个hibernate配置文件

包含hibernate运行的最基本的信息。比如,连接数据库的user和password,java class,url,数据库使用的方言Dialect。

Step 2.创建持久化类

Step 3.创建 对象-关系 映射文件

这个是ORM框架的核心基础,定义了应用实体类对应于数据库的哪一张表,属性与哪一个字段对应。

Step 4.通过Hibernate API 编写访问数据库的代码

(本文出自:https://my.oschina.net/happyBKs/blog/821006,禁 止 转 载)

下面我们逐步来看:

Step 1.创建一个hibernate配置文件

new一个文件,安装了jbosstools-4.4.2.Final-updatesite-core.zip之后(方法参考本系列上一篇博客),我们就可以方便的使用自带的Hibernate配置文件了,里面会自动为我们生成我们需要的xml标签。按照向导做即可。

172423_HKuz_1156339.png

 

172452_N7WC_1156339.png

这里我们配置数据库连接的几个基本信息,一会儿会插件为帮我们自动插入到xml配置文件中。

173935_4QNy_1156339.png

完成后如下:

com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/happybksdb
root
org.hibernate.dialect.MySQLDialect

 

看,在向导的帮助下,配置项被自动生成了。并且各个配置项都带有前缀,这些在单单使用hibernate时并不是必须的,但是在hibernate与spring集成时确实必须的。

 

比如mysql和oracle的方言在处理分页时就不一样,mysql是limit,oracle是row_number。

数据库种类的不同、版本的不同、引擎的不同,都需要我们通过方言的定义来告诉hibernate。

你可以通过查找hibernate源码中的一个配置文件(project/etc/hibernate.properties)里面罗列了可供配置的各个数据库的数据库方言的生命形式。这里罗列出来,方便日后查找复制。

DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dialect DB2 OS390 org.hibernate.dialect.DB2390Dialect PostgreSQL org.hibernate.dialect.PostgreSQLDialect MySQL org.hibernate.dialect.MySQLDialect MySQL with InnoDB org.hibernate.dialect.MySQLInnoDBDialect MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect Oracle (any version) org.hibernate.dialect.OracleDialect Oracle 9i/10g org.hibernate.dialect.Oracle9Dialect Sybase org.hibernate.dialect.SybaseDialect Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect Microsoft SQL Server org.hibernate.dialect.SQLServerDialect SAP DB org.hibernate.dialect.SAPDBDialect Informix org.hibernate.dialect.InformixDialect HypersonicSQL org.hibernate.dialect.HSQLDialect Ingres org.hibernate.dialect.IngresDialect Progress org.hibernate.dialect.ProgressDialect Mckoi SQL org.hibernate.dialect.MckoiDialect Interbase org.hibernate.dialect.InterbaseDialect Pointbase org.hibernate.dialect.PointbaseDialect FrontBase org.hibernate.dialect.FrontbaseDialect Firebird org.hibernate.dialect.FirebirdDialect 

然后我们在刚才自动生成的hibernate.cfg.xml基础上再追加一些基本配置,十分有用。

注意:我们这里已经引用了http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd,所以我们编辑hibernate.cfg.xml会自动提示。

com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/happybksdb?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
root
org.hibernate.dialect.MySQLDialect
org.hibernate.dialect.MySQLDialect
true
true
update

这里需要注意,url被声明为

jdbc:mysql://localhost:3306/happybksdb?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false

这后面加入的参数是必须要的:

characterEncoding=utf8设置了编码,这个无需多言。

serverTimezone等也是不可少的,否则你在创建SessionFactory时会报错:

Caused by: java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

还要需要注意的是url中参数之间应该是&符号分割,但是卸载xml中时,由于&有特殊意义。所以需要转义,需要写成&,否则会报错:

Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[9,126]Message: 对实体 "characterEncoding" 的引用必须以 ';' 分隔符结尾。

 

Step 2.创建持久化类

这里随便写了一个,注意,我这里没有使用注解方式,本文先以映射文件的方式来介绍。

package com.happybks.hibernate.hibernatePro.beans;import java.sql.Date;import java.sql.Timestamp;public class CuntomerBean {	private String name;	private Integer no;	private Integer cid;	private Long score;	private double money;	private Date registerDate;	private Timestamp loginTime;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public Integer getNo() {		return no;	}	public void setNo(Integer no) {		this.no = no;	}	public Integer getCid() {		return cid;	}	public void setCid(Integer cid) {		this.cid = cid;	}	public Long getScore() {		return score;	}	public void setScore(Long score) {		this.score = score;	}	public double getMoney() {		return money;	}	public void setMoney(double money) {		this.money = money;	}	public Date getRegisterDate() {		return registerDate;	}	public void setRegisterDate(Date registerDate) {		this.registerDate = registerDate;	}	public Timestamp getLoginTime() {		return loginTime;	}	public void setLoginTime(Timestamp loginTime) {		this.loginTime = loginTime;	}	public CuntomerBean() {		super();		// TODO Auto-generated constructor stub	}	@Override	public String toString() {		return "CuntomerBean [name=" + name + ", no=" + no + ", cid=" + cid + ", score=" + score + ", money=" + money				+ ", registerDate=" + registerDate + ", loginTime=" + loginTime + "]";	}			}

这里,我将例子中的各个字段涵盖了常用的各个数据类型。并且,我有意将id字段命名成cid,成员变量和属性get、set方法的顺序我也将其放到了第三位,cid也不是第一个Integer的属性(位置第一个Integer类型的属性是no),看看等会自动生成映射文件时会发生什么。

 

Step 3.创建 对象-关系 映射文件

这个应该是ORM框架的核心,建立应用实体类与数据库关系表之间的映射。

方式有两种,一种是通过映射文件,一种是通过注解的方式。本文先只介绍映射文件的方式。我们安装了jbosstools-4.4.2.Final-updatesite-core.zip就是方便,Hibernate XML Mapping file 可以自动生成。想当年刚刚自学Hibernate的时候,还傻傻地自己写Hibernate映射文件,总是一不小心写错某个小地方而导致运行错误,找错找一上午,一段令人怀念的时光。

现在操作如下:

111538_KVXh_1156339.png

111616_qdBE_1156339.png

 

111632_S0yY_1156339.png

 

114554_XPYx_1156339.png

看,自己跑出来了。

112839_1Yh4_1156339.png

值得注意的是,JBOSS的这个给eclipse的hibernate插件很智能地把cid设置成了主键。看来无论你的实体类定义中主键对应的getset属性方法、成员变量的位置是否是第一个,或者说Integer类型的第一个,只要属性的名字中带有id,都会被默认设置成为映射文件的主键id。

这里我们希望主键能够自己生成,所以做了修改。

native代表数据库自己生成。但不同数据库的生成方式不同,比如:

mysql用的是auto-increment,SQLServer用的是identity,oracle用的是序列

我们定义方言时,其实也是在告诉hibernate,在属性声明为native时,如何按照不同的数据库实现赋予主键值的方式。其他很多地方也是雷同。

然后,我们需要将我们添加的映射文件.hbm.xml添加到hibernate配置文件.cfg.cml中。这里我写的是目录结构路径。

com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/happybksdb
root
org.hibernate.dialect.MySQLDialect
org.hibernate.dialect.MySQLDialect
true
true
update

 

 

Step 4.通过Hibernate API 编写访问数据库的代码

这部分是Hibernate交互操作的基础。但这基础随着Hibernate的版本更迭居然还不停的变化。Hibernate的更新风格真是和Lucene那种前后版本应用代码不兼容的货越来越像了。

这里我先按照填坑的脚步,把各个版本的写法都注释了:

package com.happybks.hibernate.hibernatePro;import java.sql.Date;import java.sql.Timestamp;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.boot.Metadata;import org.hibernate.boot.MetadataSources;import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;import org.hibernate.boot.registry.StandardServiceRegistryBuilder;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;import org.junit.Test;import com.happybks.hibernate.hibernatePro.beans.CuntomerBean;public class HibernateTest1 {	@Test	public void test1(){		//1. 创建一个SessionFactory对象		SessionFactory sessionFactory=null;		//1.1 创建Configuration对象:对应包含hibernate的基本配置信息(cfg)和对象关系映射信息(hbm)		Configuration configuration=new Configuration().configure();				//hibernate 3.x版本的SessionFactory的创建方式,4.X被Deprecated,5.x又再次回归。		//new Configuration().buildSessionFactory();				//1.2 创建一个ServiceRegistry对象:这个对象是从Hibernate 4.x开始新增加入的		//hibernate的任务配置和服务需要在该对象中注册后才能有效。		//hibernate 4.x版本中的ServiceRegistry创建方式:ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();		//hibernate 5.x版本中的ServiceRegistry创建方式:		ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();				System.out.println(CuntomerBean.class.getCanonicalName());		Metadata metadata = new MetadataSources(serviceRegistry).addAnnotatedClass(CuntomerBean.class)				.addAnnotatedClassName(CuntomerBean.class.getName()).addResource("com/happybks/hibernate/hibernatePro/beans/CuntomerBean.hbm.xml")				.getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyJpaCompliantImpl.INSTANCE)				.build();		//1.3 创建sessionFactory		//hibernate 4.x版本中的sessionFactory创建方式: sessionFactory=configuration.buildSessionFactory(serviceRegistry);		//hibernate 5.x版本中的sessionFactory创建方式:		sessionFactory=metadata.getSessionFactoryBuilder().build();						//2. 创建一个Session对象		Session session=sessionFactory.openSession();				//3. 开启事务		Transaction transaction=session.beginTransaction();				//4. 执行保存操作。把对象保存到数据库		CuntomerBean bean=new CuntomerBean();		bean.setName("HappyBKs");		bean.setNo(314);		bean.setMoney(20688.68);		bean.setScore(98765432123456789L);		bean.setRegisterDate(new Date(new java.util.Date().getTime()));		bean.setLoginTime(Timestamp.valueOf("2017-01-08 12:00:00"));		session.save(bean);						//5. 提交事务。		transaction.commit();				//6. 关闭Session		session.close();				//7. 关闭SessionFactory对象。		sessionFactory.close();	}}

这里1.1的configure方法是重载的。可以自己制定配置文件。如

125616_Jpv5_1156339.png

configure()方法包含若干个重载的方法。configure(File )等能够通过指定配置文件来生成Configure对象。这里我们使用默认的hibernate.cfg.xml。所以只需要使用无参数的configure()方法即可。

 

我们查看configure()的源码,可以看到无参数的configure()方法就是hibernate.cfg.xml。

131222_O4Q4_1156339.png

131301_W597_1156339.png

这里插个题外话,STS的Maven设置、源代码和doc自动获取如下。以后源码什么的会自动下载到你本地的maven库。不需要你自己再下载保存整理了。

131012_6quW_1156339.png

131050_YocG_1156339.png

 

hibernate 3.x版本的SessionFactory的创建方式是new Configuration().buildSessionFactory();,4.X被Deprecated了。(这种方式在5.x又再次回归,这个最后再说。)

在4版本中,配置被当做服务注册,并以此建立SessionFactory。

Configuration conf = new Configuration().configure();ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();SessionFactory sf = conf.buildSessionFactory(serviceRegistry);

在此种方式下,Hibernate5又进行变动了。ServiceRegistryBuilder直接没有了,真粗暴!!!!早知道这样就不要引入这个类啊,你产品经理啊,变来变去。

5版本导入更换为:

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

好吧,我们将就用。

在5版本的Hibernate中,buildServiceReguistry()方法被替换了,用如下方法:

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();

不过创建SessionFactory还需要metadata,而且这个metadata需要将类名、配置文件都需要设置了。

Metadata metadata = new MetadataSources(serviceRegistry).addAnnotatedClass(CuntomerBean.class)                .addAnnotatedClassName(CuntomerBean.class.getName()).addResource("com/happybks/hibernate/hibernatePro/beans/CuntomerBean.hbm.xml")                .getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyJpaCompliantImpl.INSTANCE)                .build();sessionFactory=metadata.getSessionFactoryBuilder().build();

真要这样写出这种难以维护的代码,我宁愿用老版本了。

不过这种方式是可以运行的,咱们先看完。

数据库在运行之前,没有表。

134456_Osgy_1156339.png

运行这个测试方法。

日志如下,按照我们在cfg配置文件中设置的,输出SQL语句,还是格式化的那种。如下:说明运行成功了。一些提示最好要有密码什么的暂且忽略。

一月 08, 2017 3:22:51 下午 org.hibernate.Version logVersionINFO: HHH000412: Hibernate Core {5.2.5.Final}一月 08, 2017 3:22:51 下午 org.hibernate.cfg.Environment 
INFO: HHH000206: hibernate.properties not foundcom.happybks.hibernate.hibernatePro.beans.CuntomerBean一月 08, 2017 3:22:52 下午 org.hibernate.boot.jaxb.internal.stax.LocalXmlResourceResolver resolveEntityWARN: HHH90000012: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/hibernate-mapping. Use namespace http://www.hibernate.org/dtd/hibernate-mapping instead. Support for obsolete DTD/XSD namespaces may be removed at any time.一月 08, 2017 3:22:52 下午 org.hibernate.annotations.common.reflection.java.JavaReflectionManager
INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}一月 08, 2017 3:22:52 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configureWARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.一月 08, 2017 3:22:52 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreatorINFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/happybksdb?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false]一月 08, 2017 3:22:52 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreatorINFO: HHH10001001: Connection properties: {user=root, password=****}一月 08, 2017 3:22:52 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreatorINFO: HHH10001003: Autocommit mode: false一月 08, 2017 3:22:52 下午 org.hibernate.engine.jdbc.connections.internal.PooledConnections
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)一月 08, 2017 3:22:52 下午 org.hibernate.dialect.Dialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect一月 08, 2017 3:22:53 下午 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnectionINFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@22c01ab0] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.Hibernate: create table CUNTOMERBEAN ( CID integer not null auto_increment, NAME varchar(255), NO integer, SCORE bigint, MONEY double precision, REGISTERDATE date, LOGINTIME datetime, primary key (CID) )Hibernate: insert into CUNTOMERBEAN (NAME, NO, SCORE, MONEY, REGISTERDATE, LOGINTIME) values (?, ?, ?, ?, ?, ?)一月 08, 2017 3:22:54 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stopINFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/happybksdb?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false]

我们查看数据库,数据表已经为我们自动建立好了。(若干年前还在手写映射文件和对比数据库字段有没有检错的我泪流满面。。)

152527_o7yH_1156339.png

我们用mysql bench的生成一份建表语句,看看表的定义,与hbm映射文件中的定义字段完全一样,主键也按照设置的native,通过自己的方言,构建了属于mysql的方式:自增。(oracle和postgresql是建序列)

CREATE TABLE `cuntomerbean` (  `CID` int(11) NOT NULL AUTO_INCREMENT,  `NAME` varchar(255) DEFAULT NULL,  `NO` int(11) DEFAULT NULL,  `SCORE` bigint(20) DEFAULT NULL,  `MONEY` double DEFAULT NULL,  `REGISTERDATE` date DEFAULT NULL,  `LOGINTIME` datetime DEFAULT NULL,  PRIMARY KEY (`CID`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

查看表的记录,已经有了:

152639_sOYj_1156339.png

好吧,回到刚才的问题。这的要用metadata这种方式吗。我前面已经说了,configuration.buildSessionFactory()方法在hibernate3中被广泛使用;在4.x中被不推荐;到了5.X又回来了。我们还是用这种方式吧。

package com.happybks.hibernate.hibernatePro;import java.sql.Date;import java.sql.Timestamp;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.boot.Metadata;import org.hibernate.boot.MetadataSources;import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;import org.hibernate.boot.registry.StandardServiceRegistryBuilder;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;import org.junit.Test;import com.happybks.hibernate.hibernatePro.beans.CuntomerBean;public class HibernateTest1 {	@Test	public void test1(){		//1. 创建一个SessionFactory对象		SessionFactory sessionFactory=null;		//1.1 创建Configuration对象:对应包含hibernate的基本配置信息(cfg)和对象关系映射信息(hbm)		Configuration configuration=new Configuration().configure();				sessionFactory=configuration.buildSessionFactory();						//2. 创建一个Session对象		Session session=sessionFactory.openSession();				//3. 开启事务		Transaction transaction=session.beginTransaction();				//4. 执行保存操作。把对象保存到数据库		CuntomerBean bean=new CuntomerBean();		bean.setName("HappyBKs");		bean.setNo(314);		bean.setMoney(20688.68);		bean.setScore(98765432123456789L);		bean.setRegisterDate(new Date(new java.util.Date().getTime()));		bean.setLoginTime(Timestamp.valueOf("2017-01-08 12:00:00"));		session.save(bean);						//5. 提交事务。		transaction.commit();				//6. 关闭Session		session.close();				//7. 关闭SessionFactory对象。		sessionFactory.close();	}}

这是插入保存的基本步骤。同样,查、删、改如下:

@Test	public void test2(){		//1. 创建一个SessionFactory对象		SessionFactory sessionFactory=null;		//1.1 创建Configuration对象:对应包含hibernate的基本配置信息(cfg)和对象关系映射信息(hbm)		Configuration configuration=new Configuration().configure();		sessionFactory=configuration.buildSessionFactory();		//2. 创建一个Session对象		Session session=sessionFactory.openSession();		//3. 开启事务		Transaction transaction=session.beginTransaction();		//4. 执行保存操作。把对象保存到数据库		CuntomerBean bean=session.get(CuntomerBean.class, 1);		//5. 提交事务。		transaction.commit();		System.out.println("get bean:");		System.out.println(bean)		//6. 关闭Session		session.close();		//7. 关闭SessionFactory对象。		sessionFactory.close();	}
一月 09, 2017 10:42:48 下午 org.hibernate.Version logVersionINFO: HHH000412: Hibernate Core {5.2.5.Final}一月 09, 2017 10:42:48 下午 org.hibernate.cfg.Environment 
INFO: HHH000206: hibernate.properties not found一月 09, 2017 10:42:48 下午 org.hibernate.annotations.common.reflection.java.JavaReflectionManager
INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}一月 09, 2017 10:42:48 下午 org.hibernate.boot.jaxb.internal.stax.LocalXmlResourceResolver resolveEntityWARN: HHH90000012: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/hibernate-mapping. Use namespace http://www.hibernate.org/dtd/hibernate-mapping instead. Support for obsolete DTD/XSD namespaces may be removed at any time.一月 09, 2017 10:42:49 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configureWARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.一月 09, 2017 10:42:49 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreatorINFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/happybksdb?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false]一月 09, 2017 10:42:49 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreatorINFO: HHH10001001: Connection properties: {user=root, password=****}一月 09, 2017 10:42:49 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreatorINFO: HHH10001003: Autocommit mode: false一月 09, 2017 10:42:49 下午 org.hibernate.engine.jdbc.connections.internal.PooledConnections
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)一月 09, 2017 10:42:49 下午 org.hibernate.dialect.Dialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect一月 09, 2017 10:42:49 下午 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnectionINFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@655a5d9c] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.Hibernate: select cuntomerbe0_.CID as CID1_0_0_, cuntomerbe0_.NAME as NAME2_0_0_, cuntomerbe0_.NO as NO3_0_0_, cuntomerbe0_.SCORE as SCORE4_0_0_, cuntomerbe0_.MONEY as MONEY5_0_0_, cuntomerbe0_.REGISTERDATE as REGISTER6_0_0_, cuntomerbe0_.LOGINTIME as LOGINTIM7_0_0_ from CUNTOMERBEAN cuntomerbe0_ where cuntomerbe0_.CID=?get bean:CuntomerBean [name=HappyBKs, no=314, cid=1, score=98765432123456789, money=20688.68, registerDate=2017-01-08, loginTime=2017-01-08 12:00:00.0]一月 09, 2017 10:42:50 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stopINFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/happybksdb?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false]

现在的hibernate可以不需要在反射之后强制类型转换了,有了泛型,直接返回的就是传入的类。不难看出在映射文件里我们提供了全类名,凡是提供全类名的,基本上都是要用反射的。

 

总结与深入

以上就是Hibernate的基本步骤的概述,对于刚入门的朋友来说应该足够清楚了。

下面,因为是复习,我们队一些细节做一点点的挖掘:

创建持久化 Java 类

•提供一个无参的构造器:使Hibernate可以使用Constructor.newInstance() 来实例化持久化类

•提供一个标识属性(identifier property): 通常映射为数据库表的主键字段. (就是那个OID)如果没有该属性,一些功能将不起作用,如:Session.saveOrUpdate()

•为类的持久化类字段声明访问方法(get/set): Hibernate对JavaBeans 风格的属性实行持久化。

•使用非 final 类:

因为final的类,不能够为之生成代理。一个原因是,有的时候我们需要让这个类延迟加载,我们得到的是一个代理对象,只有是一个非final类才可以哦。

在运行时生成代理是 Hibernate 的一个重要的功能. 如果持久化类没有实现任何接口, Hibnernate 使用 CGLIB 生成代理. 如果使用的是 final 类, 则无法生成 CGLIB 代理.

•重写 eqauls 和 hashCode 方法: 如果需要把持久化类的实例放到 集合Set 中(当需要进行关联映射时), 则应该重写这两个方法

一个正常的JavaBean通常都是可以满足这些需求的,这里讲这些特性或者说要求也进行整理。

 

Hibernate 不要求持久化类继承任何父类或实现接口,这可以保证代码不被污染。这就是Hibernate被称为低侵入式设计的原因。低侵入,指的就是hibernate对javabean没有任务侵入,没有要求其实现任何接口、继承任何类,这是非常好的。

 

创建对象-关系映射文件

•Hibernate 采用 XML 格式的文件来指定对象和关系数据之间的映射. 在运行时 Hibernate 将根据这个映射文件来生成各种 SQL 语句

•映射文件的扩展名为 .hbm.xml

231206_j25R_1156339.png

 

创建 Hibernate 配置文件

•Hibernate 从其配置文件中读取和数据库连接的有关信息, 这个文件应该位于应用的 classpath 下.

230849_bvsc_1156339.png

  不同的方言会让Hibernate生成不同的SQL语句提交给不同的数据库,比如分页时,mysql用limit,oracle用row_number。

指定程序运行时是否在数据库自动生成数据表,这里我们先写update,其会自动生成。这里还可以设置其他值,我们在后面再说。

指定程序关联的映射文件,注意的是写的是目录名而不是包名。是“/”不是“.”。

 

 

使用 Hibernate 进行数据持久化操作,通常有如下步骤:

–编写持久化类: POJO + 映射文件

–获取 Configuration 对象

–获取 SessionFactory 对象

–获取 Session,打开事务

–用面向对象的方式操作数据库

–关闭事务,关闭 Session

 

Configuration 类

•Configuration 类负责管理 Hibernate 的配置信息。包括如下内容:

–Hibernate 运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。

–持久化类与数据表的映射关系(*.hbm.xml 文件)

•创建 Configuration 的两种方式

–属性文件(hibernate.properties):

•Configuration cfg = new Configuration();

–Xml文件(hibernate.cfg.xml)

•Configuration cfg = new Configuration().configure();

–Configuration 的 configure 方法还支持带参数的访问:

•File file = new File(“simpleit.xml”);

•Configuration cfg = new Configuration().configure(file);

  

SessionFactory 接口

•针对单个数据库映射关系经过编译后的内存镜像,是线程安全的

•SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息,并且配置信息不会被更改。

•SessionFactory是生成Session的工厂

•构造 SessionFactory 很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory 对象。

•Hibernate4 新增了一个 ServiceRegistry 接口,所有基于 Hibernate 的配置或者服务都必须统一向这个 ServiceRegistry  注册后才能生效

•Hibernate4 中创建 SessionFactory 的步骤

//1. 创建Configuration对象:对应包含hibernate的基本配置信息(cfg)和对象关系映射信息(hbm)Configuration configuration=new Configuration().configure();//2. 创建ServiceRegistry 对象ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();//3. 创建一个SessionFactory对象SessionFactory sessionFactory=configuration.buildSessionFactory(serviceRegistry);

 

•Hibernate5 中创建 SessionFactory 的步骤:

在3中被使用、在4中被不推荐、在5中又去除不推荐标记的configuration.buildSessionFactory();方法使用方式如下:

Configuration configuration=new Configuration().configure();SessionFactory sessionFactory=configuration.buildSessionFactory();

在4中注册服务的方式在5中就没有对应的API了,引入了StandardServiceRegistryBuilder类。相关方法也有变动。

Configuration configuration=new Configuration().configure();ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();Metadata metadata = new MetadataSources(serviceRegistry).addAnnotatedClass(CuntomerBean.class)				.addAnnotatedClassName(CuntomerBean.class.getName()).addResource("com/happybks/hibernate/hibernatePro/beans/CuntomerBean.hbm.xml")				.getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyJpaCompliantImpl.INSTANCE)				.build();SessionFactory sessionFactory=configuration.buildSessionFactory();

 

Session 接口

我们通过下面两者图来对比,或者说对应着看Hibernate和JDBC实现客户端应用于数据库交互的几个环节。

Hibernate的SessionFactory对应于JDBC的ConnectionPool,Hibernate的Session对应于JDBC的JDBC Connection。不过,Hibernate的Session与数据库的交互还是建立在JDBC Connection上的,可以理解为Hibernate的Session是对JDBC Connection的包装。

212043_BnRi_1156339.png

•Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。

对象的生命周期中有一种状态叫做持久化状态,即对象和Session关联的时候,对象它才能被称为持久化状态。也只有处于持久化状态,Hibernate才能够感知对象属性的变化。

此对象的生命周期很短。Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处。相当于 JDBC 中的 Connection。

•持久化类与 Session 关联起来后就具有了持久化的能力。

•Session 类的方法:

–取得持久化对象的方法: get() load()

–持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()

–开启事务: beginTransaction().

–管理 Session 的方法:isOpen(),flush(), clear(), evict(), close()等

 

Transaction(事务)

•代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。修改的操作更不用说了。

写代码的时候如果把事务的开和提交忘记,你插入数据,即使你能看到SQL语句在日志输出,但是数据库里实际没有插入任何数据。

  Transaction tx = session.beginTransaction();

•常用方法:

–commit():提交相关联的session实例

–rollback():撤销事务操作

–wasCommitted():检查事务是否提交

 

Hibernate 配置文件的两个配置项

•hbm2ddl.auto:该属性可帮助程序员实现正向工程, 即由 java 代码生成数据库脚本, 进而生成具体的表结构. 。取值 create | update | create-drop | validate

create : 会根据 .hbm.xml  文件来生成数据表, 但是每次运行都会删除上一次的表 ,重新生成表, 哪怕二次没有任何改变

create-drop : 会根据 .hbm.xml 文件生成表,但是SessionFactory一关闭, 表就自动删除

update : 最常用的属性值,也会根据 .hbm.xml 文件生成表, 但若 .hbm.xml  文件和数据库中对应的数据表的表结构不同, Hiberante  将更新数据表结构,但不会删除已有的行和列

validate : 会和数据库中的表进行比较, 若 .hbm.xml 文件中的列在数据表中不存在,则抛出异常

•format_sql:是否将 SQL 转化为格式良好的 SQL . 取值 true | false

 

 

 

转载于:https://my.oschina.net/happyBKs/blog/821006

你可能感兴趣的文章
使用Notepad++实现批量将ANSI转成为UTF-8编码
查看>>
Codeforces Round #280 (Div. 2) E. Vanya and Field 思维题
查看>>
HDU 1004 Let the Balloon Rise【STL<map>】
查看>>
Java千百问_05面向对象(006)_is-a,has-a,like-a是什么
查看>>
【Python】python更新数据库脚本两种方法
查看>>
linux进程同步机制_转
查看>>
PHP框架认识初步
查看>>
给 Android 初学者的 Gradle 知识普及
查看>>
分模块开发创建Action子模块——(九)
查看>>
基于Nginx实现一个自己的HTTP模块
查看>>
LeetCode(34)-Palindrome Number
查看>>
阅读《Android 从入门到精通》(24)——切换图片
查看>>
SimpleDateFormat线程不安全及解决的方法
查看>>
Unity---------Mesh理解
查看>>
hdu 1728 逃离迷宫 bfs记转向
查看>>
一分钟学会 ConstraintLayout 之从属性角度理解布局
查看>>
线程 Timer TimerTask 计时器 定时任务 MD
查看>>
[js高手之路]原型式继承与寄生式继承
查看>>
MBR分区操作-增加、扩展、删除
查看>>
php如何互换一个数组的首尾元素 中间不变 首尾互换
查看>>