Hibernate实战(第二版)笔记----第二章--开启一个项目

2024-06-17 05:48

本文主要是介绍Hibernate实战(第二版)笔记----第二章--开启一个项目,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近在看Hibernate实战(第二版)这本书,个人感觉翻译的不是很好,有些地方读都读不通。。。




随便做下笔记,书中提供下载源码的地址为: http://jpwh.org 




下载下来之后,目录如下




其中:

apps----第18/19章对应的客服端与服务端程序

environment----一些通用的环境

examples----一些实例

model---一些实体类

shared---共享的一些帮助类什么的


README.txt说明文件如下:


==============================================================================
Java Persistence with Hibernate - Second Editionhttp://www.manning.com/bauer3/==============================================================================入门
------------------------------------------------------------------------------- Install JDK 7.- Install Maven 3.x.- 运行'mvn clean test'来执行所有的例子(这将需要一段时间依赖关系必须首次下载)。- 打开报告 examples/target/surefire-reports/index.html- 详细了解每个子目录的pom.xml文件中的模块并进行浏览源代码。- 获取更多的日志输出, 编辑 shared/src/main/resources/logging.properties并运行测试。 所有日志输出都将写入文件examples/target/surefire-reports/TestSuite-output.txt- 要仅运行单个测试,请先将模块安装到您的本地Maven中存储库使用'mvn clean install'。 然后运行测试:mvn -pl examples -Dtest=org.jpwh.test.simple.CRUD clean test- 如果只运行单个测试,则控制台日志输出将被写入在以前的情况下,一个不同的文件:examples/target/surefire-reports/org.jpwh.test.simple.CRUD-output.txt运行示例APPS
------------------------------------------------------------------------------- 安装Wildfly 8.2.0.Final- 在后台使用 $WILDFLY/bin/standalone.sh运行应用程序服务器- 运行 "Stateless Client/Server" 示例应用程序:mvn -P app-stateless-server clean installmvn -P app-stateless-server clean package wildfly:deploymvn -P app-stateless-client clean testmvn -P app-stateless-server clean package wildfly:undeploy- Run the "Stateful Client/Server" example app:mvn -P app-stateful-server clean installmvn -P app-stateful-server clean package wildfly:deploymvn -P app-stateful-client clean testmvn -P app-stateful-server clean package wildfly:undeploy- Run the "CaveatEmptor Web Application" example:mvn -P app-web clean package wildfly:deployOpen in browser: http://localhost:8080/app-web/mvn -P app-web wildfly:undeploy运行/浏览外部数据库
------------------------------------------------------------------------------- 默认情况下,使用内存中H2数据库实例进行测试。 你不能使用SQL控制台访问和浏览此数据库。 如果你只想看看模式/SQL,如上所述编辑logging.properties。- 您可以切换到外部已经运行的H2数据库。 首先启动数据库通过双击H2.jar文件。 它应该在你的Maven存储库(~/.m2/repository/com/h2database/)或者你可以从它下载http://h2database.com。 H2网页控制台将打开,你可以简单的用户'sa'连接到数据库实例,没有密码。- 将示例模块安装到本地存储库中:mvn clean install- 运行单个测试方法,并在完成后保留模式/数据:mvn -pl examples \-Dtest=org.jpwh.test.simple.CRUD#storeAndQueryItems \-DconnectionURL=jdbc:h2:tcp://localhost/mem:test \-DkeepSchema=true \clean test- 在H2控制台中执行测试方法后浏览数据库。- 您可以再次执行相同的测试方法,数据库将被清理在方法运行之前。 您可以执行相同测试的其他方法类,每个测试类使用相同的数据库模式。- 要执行另一个具有不同模式的测试类的方法,请停止在切换测试类时启动H2数据库。请注意,H2删除最后一个连接时的内存数据库。如果在H2 web控制台断开连接,数据库将被删除。------------------------------------------------------------------------------Visit us on the Manning author forum:http://www.manning-sandbox.com/forum.jspa?forumID=844



打开Eclipse选择Import




选择一个存在的Maven项目




然后点击Finish,完成导入,导入成功之后如下:




导入之后,会报很多错:


比如说这几个类CreditCard_、 Item_ 、Bid_提示找不到,我找了半天在书中对应的论坛找到了一种说法:https://forums.manning.com/posts/list/35484.page




暂时把那些报错的地方全部注释掉。然后对照着书中的第二章的开启一个项目,运行测试,发现测试用的TestNG框架,然后把TestNG插件装上


(一)、使用JPA的"Hello Word"


它这里使用了持久化单元,什么是持久化单元,网上的解释是,一个持久化单元(Persistence Unit)就是关于一组Entity类的命名配置。持久化单元是一个静态的概念,持久性单元具有唯一的名称,负责定义应用中的一组实体如何进行管理和持久性。在应用中使用persistence.xml文件来设置持久性单元,可以配置多个持久性单元,但每个单元拥有唯一的名称。

持久性单元包含的属性有:


1.在该持久性单元范围(作用域)内的实体类
2.为上述实体类提供持久性的持久性提供者(Persistence Provider)或库
3.上述实体类的数据源(Data Source)
4.应用使用的事务类型(Transaction Type)
5.持久性单元能够被打包成WAR文件,EJB-JAR文件,EAR文件的一部分,或者直接打包成应用程序能够直接使用的JAR文件。

持久性单元的范围(作用域)取决于persistence.xml文件的位置。一般说来,IDE能够使用引导界面来正确放置persistence.xml的位置。例如使用IDE为EJB模块(Module)创建的持久性单元,persistence.xml文件将被放在EJB模块的src/conf目录中,当你将模块打包时,persistence.xml文件被放在EJB JAR文件的META-INF目录中。这样持久性单元的作用域就是EJB JAR文件中的类。

注意:persistence.xml文件的位置决定持久性的根(Persistence Root)。持久性的根为JAR文件或者包含META-INF目录(前提是persistence.xml位于此)的目录。


JPA规范要求在类路径的META-INF目录下放置persistence.xml, 文件的名称是固定的,配置模板如下: 


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"xmlns="<a target=_blank href="http://xmlns.jcp.org/xml/ns/persistence">http://xmlns.jcp.org/xml/ns/persistence</a>" xmlns:xsi="<a target=_blank href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"xsi:schemaLocation="<a target=_blank href="http://xmlns.jcp.org/xml/ns/persistence">http://xmlns.jcp.org/xml/ns/persistence</a><a target=_blank href="http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd</a>"><persistence-unit name="persist-unit" transaction-type="RESOURCE_LOCAL"><provider>org.eclipse.persistence.jpa.PersistenceProvider</provider><!-- All persistence classes must be listed --><class>boa.framework.entity.CustomerEntity</class>                                                                                 <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode><validation-mode>CALLBACK</validation-mode>     <properties><!-- Provider-specific connection properties --><property name="javax.persistence.jdbc.url" value="jdbc:derby:memory:exampleDB;create=true" /><property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" /><property name="javax.persistence.jdbc.user" value="" /><property name="javax.persistence.jdbc.password" value="" /><property name="javax.persistence.schema-generation.database.action"value="drop-and-create" /><property name="javax.persistence.schema-generation.create-source"value="script" /><property name="javax.persistence.schema-generation.create-script-source"value="META-INF/create-script.sql" /><property name="eclipseink.logging.level" value="INFO" /></properties></persistence-unit><!--   Name属性用于定义持久化单元的名字 (name必选,空值也合法);   transaction-type 指定事务类型(可选)   -->  <persistence-unit name="unitName" transaction-type="JTA">  <!-- 描述信息.(可选) -->  <description> </description>  <!-- javax.persistence.PersistenceProvider接口的一个实现类(可选) -->  <provider>   </provider>  <!-- Jta-data-source和 non-jta-data-source用于分别指定持久化提供商使用的JTA和/或non-JTA数据源的全局JNDI名称(可选) -->  <jta-data-source>java:/test</jta-data-source>  <non-jta-data-source> </non-jta-data-source>  <!-- 声明orm.xml所在位置.(可选) -->  <mapping-file>product.xml</mapping-file>  <!-- 以包含persistence.xml的jar文件为基准的相对路径,添加额外的jar文件.(可选) -->  <jar-file>../lib/model.jar</jar-file>  <!-- 显式列出实体类,在Java SE 环境中应该显式列出.(可选) -->  <class>boa.framework.entity.CustomerEntity</class><!-- 声明是否扫描jar文件中标注了@Enity类加入到上下文.若不扫描,则如下:(可选) -->  <exclude-unlisted-classes>true</exclude-unlisted-classes> shared-cache-mode缓存模式。加了@Cacheable注解的默认为二级缓存。有四种模式:ALL-缓存所有实体;NONE-禁止缓存;ENABLE_SELECTIVE-如果加了缓存的标识,是默认的选选        项;DISABLE_SELECTIVE- enable caching unless explicitly marked as  @Cacheable(false) (not  recommended)validation-mode实体的验证模式,默认是激活的。当一个实体在创建、更新,在实体发送到数据库前会被进行验证。CALLBACK: entities are validated on creation, update and deletion. If no Bean Validation provider  is present, an exception is raised at initialization time.                        <!--    厂商专有属性(可选)    -->  <properties>  <!-- hibernate.hbm2ddl.auto= create-drop / create / update -->  <property name="eclipseink.logging.level" value="INFO" />  </properties>  </persistence-unit>  </persistence>  


本示例中的persistence.xml内容为:


<persistenceversion="2.1"xmlns="http://xmlns.jcp.org/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistencehttp://xmlns.jcp.org/xml/ns/persistence_2_1.xsd"><!-- <code>persistence.xml</code>文件至少配置一个持久化单元;每个单元必须有一个唯一的名称。--><persistence-unit name="HelloWorldPU"><!-- 每个持久化单元必须有一个数据库连接。在这里你委托给现有的<code>java.sql.DataSource</code>。Hibernate会找到数据源通过在启动时使用JNDI查找来命名。--><jta-data-source>myDS</jta-data-source><!-- 持久单元有持久的(映射)类,您将它们列在这里。       --><class>org.jpwh.model.helloworld.Message</class><!-- Hibernate可以为映射的类扫描类路径并自动添加它们给你的坚持单位。这种设置禁用了该特性。--><exclude-unlisted-classes>true</exclude-unlisted-classes><!-- 可以将标准或供应商特定的选项设置为持久性单元的属性。任何标准属性都有 <code>javax.persistence</code> 名称前缀,使用Hibernate的设置 <code>hibernate</code>--><properties><!-- JPA引擎应该在启动时自动删除和重新创建数据库中的SQL模式。对于自动化测试来说,这是非常理想的,当您想要为每个测试运行使用一个干净的数据库时。--><propertyname="javax.persistence.schema-generation.database.action"value="drop-and-create"/><!-- 当在日志中打印SQL时,让Hibernate格式化SQL并将注释生成到SQL字符串中,这样我们就可以知道为什么Hibernate执行SQL语句了--><property name="hibernate.format_sql" value="true"/><property name="hibernate.use_sql_comments" value="true"/><!-- 禁用Hibernate扫描,我们也不需要任何的hbm.xml文件。它会发现并自动添加的xml文件 --><property name="hibernate.archive.autodetection" value="none"/></properties></persistence-unit></persistence>

里面有很多,这里删除了一些。


找到examples中的HelloWorldJPA

package org.jpwh.helloworld;import org.jpwh.env.TransactionManagerTest;
import org.jpwh.model.helloworld.Message;
import org.testng.annotations.Test;import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.transaction.UserTransaction;
import java.util.List;import static org.testng.Assert.assertEquals;public class HelloWorldJPA extends TransactionManagerTest {@Testpublic void storeLoadMessage() throws Exception {EntityManagerFactory emf =Persistence.createEntityManagerFactory("HelloWorldPU");try {//初始化代码块{/* 访问标准事务API <code>UserTransaction</code>和在执行的线程上启动事务。*/UserTransaction tx = TM.getUserTransaction();tx.begin();/* 通过创建一个<code>EntityManager</code>来开始一个新的会话是所有持久性操作的上下文。*/EntityManager em = emf.createEntityManager();/* Create a new instance of the mapped domain model class <code>Message</code> andset its <code>text</code> property.*/Message message = new Message();message.setText("Hello World!");/* 使用持久性上下文来列举瞬态实例,使其持续存在。Hibernate现在知道你想存储的数据,它不一定调用数据库,但是。*/em.persist(message);/* 提交事务,Hibernate现在自动检查持久化上下文执行必要的SQL <code>INSERT</code>语句。*/tx.commit();// INSERT into MESSAGE (ID, TEXT) values (1, 'Hello World!')/* If you create an <code>EntityManager</code>, you must close it.*/em.close();}{/* 每个与数据库的交互都应该在显式事务边界内发生,即使你只是在阅读数据。*/UserTransaction tx = TM.getUserTransaction();tx.begin();EntityManager em = emf.createEntityManager();/* 执行一个查询,以从数据库检索<code>Message</code>的所有实例。*/List<Message> messages =em.createQuery("select m from Message m").getResultList();// SELECT * from MESSAGEassertEquals(messages.size(), 1);assertEquals(messages.get(0).getText(), "Hello World!");/* 您可以更改属性的值,Hibernate会自动检测到这一点,因为加载的<code>Message</code>仍然依附于它所加载的持久化上下文。*/messages.get(0).setText("Take me to your leader!");/* On commit, Hibernate checks the persistence context for dirty state and executes theSQL <code>UPDATE</code> automatically to synchronize the in-memory with the database state.*/tx.commit();// UPDATE MESSAGE set TEXT = 'Take me to your leader!' where ID = 1em.close();}} finally {TM.rollback();emf.close();}}}

项目右键Run AS---> TestNG运行




输出如下:


PASSED: storeLoadMessage===============================================Default testTests run: 1, Failures: 0, Skips: 0
===============================================七月 03, 2017 3:44:03 下午 bitronix.tm.BitronixTransactionManager shutdown
信息: shutting down Bitronix Transaction Manager===============================================
Default suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================[TestNG] Time taken by org.testng.reporters.jq.Main@5fdef03a: 25 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 1 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@77556fd: 4 ms
[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@14899482: 4 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@16b3fc9e: 26 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@ed17bee: 4 ms


接下来分析下他的源码,HelloWorldJPA继承TransactionManagerTest


/environment/src/main/java/org/jpwh/env/TransactionManagerTest.java的内容如下:


package org.jpwh.env;import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;import java.util.Locale;/*** 在测试套件中启动和停止事务管理器/数据库池* <p>* 一个套件中的所有测试都是单个执行的 {@link TransactionManagerSetup}, * 调用静态 {@link TransactionManagerTest#TM} * 在您的测试中访问JTA事务管理器和数据库连接。* </p>* <p>* 测试参数 <code>database</code> (指定一个支持* {@link DatabaseProduct}) 和一个 <code>connectionURL</code> * 默认设置是内存中的H2数据库实例,为每个测试套件自动创建和销毁* </p>*/
public class TransactionManagerTest {// 每个测试套件静态单数据库连接管理器static public TransactionManagerSetup TM;@Parameters({"database", "connectionURL"})@BeforeSuite()public void beforeSuite(@Optional String database,@Optional String connectionURL) throws Exception {TM = new TransactionManagerSetup(//默认使用H2数据库database != null? DatabaseProduct.valueOf(database.toUpperCase(Locale.US)): DatabaseProduct.H2,connectionURL);}@AfterSuite(alwaysRun = true)public void afterSuite() throws Exception {if (TM != null)TM.stop();}
}



他里面加了这个类TransactionManagerSetup


/environment/src/main/java/org/jpwh/env/TransactionManagerSetup.java


package org.jpwh.env;import bitronix.tm.TransactionManagerServices;
import bitronix.tm.resource.jdbc.PoolingDataSource;import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import java.util.logging.Logger;/***提供与Bitronix JTA事务的数据库连接池* manager(http://docs.codehaus.org/display/BTM/Home)。* <p>* Hibernate将通过查找数据源和<code> UserTransaction </code>* 通过JNDI,这就是为什么你还需要一个<code> jndi.properties </code>文件。最小的* JNDI上下文与Bitronix绑定并启动。* </p>*/
public class TransactionManagerSetup {//数据源名称public static final String DATASOURCE_NAME = "myDS";private static final Logger logger =Logger.getLogger(TransactionManagerSetup.class.getName());protected final Context context = new InitialContext();protected final PoolingDataSource datasource;public final DatabaseProduct databaseProduct;public TransactionManagerSetup(DatabaseProduct databaseProduct) throws Exception {this(databaseProduct, null);}public TransactionManagerSetup(DatabaseProduct databaseProduct,String connectionURL) throws Exception {logger.fine("Starting database connection pool");logger.fine("Setting stable unique identifier for transaction recovery");TransactionManagerServices.getConfiguration().setServerId("myServer1234");logger.fine("Disabling JMX binding of manager in unit tests");TransactionManagerServices.getConfiguration().setDisableJmx(true);logger.fine("Disabling transaction logging for unit tests");TransactionManagerServices.getConfiguration().setJournal("null");logger.fine("Disabling warnings when the database isn't accessed in a transaction");TransactionManagerServices.getConfiguration().setWarnAboutZeroResourceTransaction(false);logger.fine("Creating connection pool");datasource = new PoolingDataSource();datasource.setUniqueName(DATASOURCE_NAME);datasource.setMinPoolSize(1);datasource.setMaxPoolSize(5);datasource.setPreparedStatementCacheSize(10);//我们的锁定/版本控制测试假设读取提交的事务//隔离。这不是默认的MySQL InnoDB,所以我们设置//明确地在这里。datasource.setIsolationLevel("READ_COMMITTED");//Hibernate的SQL模式生成器调用connection.setAutoCommit(true)//当EntityManager处于挂起状态时,我们使用自动提交模式//模式,并没有加入一个事务。datasource.setAllowLocalTransactions(true);logger.info("Setting up database connection: " + databaseProduct);this.databaseProduct = databaseProduct;databaseProduct.configuration.configure(datasource, connectionURL);logger.fine("Initializing transaction and resource management");datasource.init();}public Context getNamingContext() {return context;}public UserTransaction getUserTransaction() {try {return (UserTransaction) getNamingContext().lookup("java:comp/UserTransaction");} catch (Exception ex) {throw new RuntimeException(ex);}}public DataSource getDataSource() {try {return (DataSource) getNamingContext().lookup(DATASOURCE_NAME);} catch (Exception ex) {throw new RuntimeException(ex);}}public void rollback() {UserTransaction tx = getUserTransaction();try {if (tx.getStatus() == Status.STATUS_ACTIVE ||tx.getStatus() == Status.STATUS_MARKED_ROLLBACK)tx.rollback();} catch (Exception ex) {System.err.println("Rollback of transaction failed, trace follows!");ex.printStackTrace(System.err);}}public void stop() throws Exception {logger.fine("Stopping database connection pool");datasource.close();TransactionManagerServices.getTransactionManager().shutdown();}}

它其中还引用了databaseProduct类databaseProduct类是一个枚举类型的,定义了一些数据库


/environment/src/main/java/org/jpwh/env/DatabaseProduct.java

package org.jpwh.env;import bitronix.tm.resource.jdbc.PoolingDataSource;import java.util.Properties;public enum DatabaseProduct {H2(new DataSourceConfiguration() {@Overridepublic void configure(PoolingDataSource ds, String connectionURL) {ds.setClassName("org.h2.jdbcx.JdbcDataSource");// External instance: jdbc:h2:tcp://localhost/mem:test;USER=sads.getDriverProperties().put("URL",connectionURL != null? connectionURL :"jdbc:h2:mem:test");// TODO: http://code.google.com/p/h2database/issues/detail?id=502ds.getDriverProperties().put("user", "sa");// TODO: Don't trace log values larger than X bytes (especially useful for// debugging LOBs, which are accessed in toString()!)// System.setProperty("h2.maxTraceDataLength", "256"); 256 bytes, default is 64 kilobytes}},org.jpwh.shared.ImprovedH2Dialect.class.getName()),ORACLE(new DataSourceConfiguration() {@Overridepublic void configure(PoolingDataSource ds, String connectionURL) {ds.setClassName("oracle.jdbc.xa.client.OracleXADataSource");ds.getDriverProperties().put("URL",connectionURL != null? connectionURL :"jdbc:oracle:thin:test/test@192.168.56.101:1521:xe");// Required for reading VARBINARY/LONG RAW columns easily, see// http://stackoverflow.com/questions/10174951Properties connectionProperties = new Properties();connectionProperties.put("useFetchSizeWithLongColumn", "true");ds.getDriverProperties().put("connectionProperties", connectionProperties);}},org.hibernate.dialect.Oracle10gDialect.class.getName()),POSTGRESQL(new DataSourceConfiguration() {@Overridepublic void configure(PoolingDataSource ds, String connectionURL) {ds.setClassName("org.postgresql.xa.PGXADataSource");if (connectionURL != null) {throw new IllegalArgumentException("PostgreSQL XADataSource doesn't support connection URLs");}ds.getDriverProperties().put("serverName", "10.0.0.2");ds.getDriverProperties().put("databaseName", "test");ds.getDriverProperties().put("user", "test");ds.getDriverProperties().put("password", "test");}},org.hibernate.dialect.PostgreSQL82Dialect.class.getName()),MYSQL(new DataSourceConfiguration() {@Overridepublic void configure(PoolingDataSource ds, String connectionURL) {// TODO: MySQL XA support is completely broken, we use the BTM XA wrapper//ds.setClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");ds.setClassName("bitronix.tm.resource.jdbc.lrc.LrcXADataSource");ds.getDriverProperties().put("url",connectionURL != null? connectionURL :"jdbc:mysql://localhost/test?sessionVariables=sql_mode='PIPES_AS_CONCAT'");ds.getDriverProperties().put("driverClassName", "com.mysql.jdbc.Driver");}},// Yes, this should work with 5.6, no idea why Gail named it 5.7org.hibernate.dialect.MySQL57InnoDBDialect.class.getName());public DataSourceConfiguration configuration;public String hibernateDialect;private DatabaseProduct(DataSourceConfiguration configuration,String hibernateDialect) {this.configuration = configuration;this.hibernateDialect = hibernateDialect;}public interface DataSourceConfiguration {void configure(PoolingDataSource ds, String connectionURL);}}


(二)、原生Hibernate配置


HelloWorldHibernate测试类


/examples/src/test/java/org/jpwh/helloworld/HelloWorldHibernate.java

package org.jpwh.helloworld;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl;
import org.hibernate.service.ServiceRegistry;
import org.jpwh.env.TransactionManagerTest;
import org.jpwh.model.helloworld.Message;
import org.testng.annotations.Test;import javax.transaction.UserTransaction;
import java.util.List;import static org.testng.Assert.*;public class HelloWorldHibernate extends TransactionManagerTest {protected void unusedSimpleBoot() {SessionFactory sessionFactory = new MetadataSources(new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build()).buildMetadata().buildSessionFactory();}protected SessionFactory createSessionFactory() {/* 此构建器可帮助您创建不可变服务注册表链接方法调用。*/StandardServiceRegistryBuilder serviceRegistryBuilder =new StandardServiceRegistryBuilder();/* 通过应用设置配置服务注册表。*/serviceRegistryBuilder.applySetting("hibernate.connection.datasource", "myDS").applySetting("hibernate.format_sql", "true").applySetting("hibernate.use_sql_comments", "true").applySetting("hibernate.hbm2ddl.auto", "create-drop");// 启用JTA(这有点粗糙,因为Hibernate开发人员仍然相信JTA是// 仅用于怪异的应用服务器,您将永远不会看到此代码)。serviceRegistryBuilder.applySetting(Environment.TRANSACTION_COORDINATOR_STRATEGY,JtaTransactionCoordinatorBuilderImpl.class);ServiceRegistry serviceRegistry = serviceRegistryBuilder.build();/* 您只能使用现有服务注册表输入此配置阶段。        */MetadataSources metadataSources = new MetadataSources(serviceRegistry);/* 将持久化类添加到(映射)元数据源。         */metadataSources.addAnnotatedClass(org.jpwh.model.helloworld.Message.class);// 添加hbm.xml映射文件// metadataSources.addFile(...);// 从JAR读取所有hbm.xml映射文件// metadataSources.addJar(...)MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder();Metadata metadata = metadataBuilder.build();assertEquals(metadata.getEntityBindings().size(), 1);SessionFactory sessionFactory = metadata.buildSessionFactory();return sessionFactory;}@Testpublic void storeLoadMessage() throws Exception {SessionFactory sessionFactory = createSessionFactory();try {{/* 访问标准事务API <code> UserTransaction </code>和在这个执行线程上开始一个事务。*/UserTransaction tx = TM.getUserTransaction();tx.begin();/* 每当你在同一个线程中调用<code> getCurrentSession()</code>相同的<code> org.hibernate.Session </code>。 它会自动被绑定到正在进行的事务,在该事务时自动关闭提交或回滚。*/Session session = sessionFactory.getCurrentSession();Message message = new Message();message.setText("Hello World!");/* 本机Hibernate API与标准的Java Persistence API和大多数方法非常相似有相同的名字。*/session.persist(message);/* Hibernate将会话与数据库同步并关闭“当前”会话自动提交绑定事务。*/tx.commit();// INSERT into MESSAGE (ID, TEXT) values (1, 'Hello World!')}{UserTransaction tx = TM.getUserTransaction();tx.begin();/* Hibernate标准查询是表达查询的类型安全的编程方式,自动翻译成SQL。*/List<Message> messages =sessionFactory.getCurrentSession().createCriteria(Message.class).list();// SELECT * from MESSAGEassertEquals(messages.size(), 1);assertEquals(messages.get(0).getText(), "Hello World!");tx.commit();}} finally {TM.rollback();}}
}

总结:


本章主要讲解了两种持久化API的用法

1、EntityManagerFactory
2、SessionFactory


对于这两种方法的区别可查考这:http://javabeat.net/jpa-entitymanager-vs-hibernate-sessionfactory/?utm_source=tuicool&utm_medium=referral 我把它翻译下


JPA EntityManagerFactory Vs Hibernate’s SessionFactory


如果你正在使用JPA的标准规范执行(读:介绍JPA),然后您可以使用EntityManagerFactory打开会话。但是,如果您使用的是Hibernate实现,你有Hibernate特定SessionFactory管理会议。这里有很多开发者喜欢哪一个是最好的方法混淆。在这里,有两种意见是受欢迎的:


1、EntityManagerFactory是标准实现,在所有实现中都是相同的。如果我们将ORM迁移到任何其他提供者,处理事务的方法将不会发生任何变化。相反,如果使用hibernate的会话工厂,它与hibernate api绑定,不会轻易迁移到新的供应商。


2、使用标准实现的一个不利之处在于它不提供高级功能。 在EntityManager API中没有提供很多控件。 而Hibernate的SessionFactory有很多高级功能,在JPA中无法完成。 一个这样的事情是检索ID生成器而不关闭事务,批量插入等。


看了以上几点,必须决定哪一个是更好的。没有硬性规定,毕竟这取决于开发商的要求。另一个建议是,我们可以用实体和会话工厂经理一起。在这种方法中,实体管理代表会议处理Hibernate通过调用Unwrap方法。这样地:


Session session = entityManager.unwrap(Session.class);


使用EntityManagerFactory方法,我们可以使用@PrePersist,@ PostPersist,@PreUpdate等回调方法注释,无需额外的配置。 使用SessionFactory时使用类似的回调需要额外的努力。


这篇关于Hibernate实战(第二版)笔记----第二章--开启一个项目的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1068629

相关文章

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

AssetBundle学习笔记

AssetBundle是unity自定义的资源格式,通过调用引擎的资源打包接口对资源进行打包成.assetbundle格式的资源包。本文介绍了AssetBundle的生成,使用,加载,卸载以及Unity资源更新的一个基本步骤。 目录 1.定义: 2.AssetBundle的生成: 1)设置AssetBundle包的属性——通过编辑器界面 补充:分组策略 2)调用引擎接口API

如何开启和关闭3GB模式

https://jingyan.baidu.com/article/4d58d5414dfc2f9dd4e9c082.html

用Microsoft.Extensions.Hosting 管理WPF项目.

首先引入必要的包: <ItemGroup><PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /><PackageReference Include="Serilog

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

持久层 技术选型如何决策?JPA,Hibernate,ibatis(mybatis)

转自:http://t.51jdy.cn/thread-259-1-1.html 持久层 是一个项目 后台 最重要的部分。他直接 决定了 数据读写的性能,业务编写的复杂度,数据结构(对象结构)等问题。 因此 架构师在考虑 使用那个持久层框架的时候 要考虑清楚。 选择的 标准: 1,项目的场景。 2,团队的技能掌握情况。 3,开发周期(开发效率)。 传统的 业务系统,通常业

《offer来了》第二章学习笔记

1.集合 Java四种集合:List、Queue、Set和Map 1.1.List:可重复 有序的Collection ArrayList: 基于数组实现,增删慢,查询快,线程不安全 Vector: 基于数组实现,增删慢,查询快,线程安全 LinkedList: 基于双向链实现,增删快,查询慢,线程不安全 1.2.Queue:队列 ArrayBlockingQueue:

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

操作系统实训复习笔记(1)

目录 Linux vi/vim编辑器(简单) (1)vi/vim基本用法。 (2)vi/vim基础操作。 进程基础操作(简单) (1)fork()函数。 写文件系统函数(中等) ​编辑 (1)C语言读取文件。 (2)C语言写入文件。 1、write()函数。  读文件系统函数(简单) (1)read()函数。 作者本人的操作系统实训复习笔记 Linux