JavaPersistenceWithHibernate第二版笔记Getting started with ORM-001用JPA和Hibernate实现HellowWorld(JTA、Bitronix)
一、结构
二、model层
1.
- package org.jpwh.model.helloworld;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- /*
- Every persistent entity class must have at least the <code>@Entity</code> annotation.
- Hibernate maps this class to a table called <code>MESSAGE</code>.
- */
- @Entity
- public class Message {
- /*
- Every persistent entity class must have an identifier
- attribute annotated with <code>@Id</code>. Hibernate maps
- this attribute to a column named <code>ID</code>.
- */
- @Id
- /*
- Someone must generate identifier values; this annotation enables
- automatic generation of IDs.
- */
- @GeneratedValue//(strategy=GenerationType.TABLE)
- private Long id;
- /*
- You usually implement regular attributes of a persistent class with private
- or protected fields, and public getter/setter method pairs. Hibernate maps
- this attribute to a column called <code>TEXT</code>.
- */
- private String text;
- public String getText() {
- return text;
- }
- public void setText(String text) {
- this.text = text;
- }
- }
三、配置文件
1.persistence.xml(这个文件似乎不起作用)
- <persistence
- version="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/persistence
- http://xmlns.jcp.org/xml/ns/persistence_2_1.xsd">
- <!--
- The <code>persistence.xml</code> file configures at least one persistence unit;
- each unit must have a unique name.
- -->
- <persistence-unit name="HelloWorldPU">
- <!--
- Each persistence unit must have a database connection. Here you delegate to
- an existing <code>java.sql.DataSource</code>. Hibernate will find the data source
- by name with a JNDI lookup on startup.
- -->
- <!-- delegate database connection handling to a
- Java Transaction API ( JTA ) provider, the open source Bitronix project. -->
- <jta-data-source>myDS2</jta-data-source>
- <!--
- A persistent unit has persistent (mapped) classes, you list them here.
- -->
- <class>org.jpwh.model.helloworld.Message</class>
- <!--
- Hibernate can scan your classpath for mapped classes and add them automatically
- to your persistence unit. This setting disables that feature.
- -->
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- <!--
- Standard or vendor-specific options can be set as properties on a persistence unit.
- Any standard properties have the <code>javax.persistence</code> name prefix, Hibernate's
- settings use <code>hibernate</code>
- -->
- <properties>
- <!--
- The JPA engine should drop and re-create the SQL schema in the database
- automatically when it boots. This is ideal for automated testing, when
- you want to work with a clean database for every test run.
- -->
- <property
- name="javax.persistence.schema-generation.database.action"
- value="update"/>
- <!-- drop-and-create -->
- <!--
- When printing SQL in logs, let Hibernate format the SQL nicely and generate
- comments into the SQL string so we know why Hibernate executed the SQL statement.
- -->
- <property name="hibernate.format_sql" value="true"/>
- <property name="hibernate.use_sql_comments" value="true"/>
- <!-- Disable Hibernate scanning completely, we also don't want any hbm.xml files
- discovered and added automatically. -->
- <property name="hibernate.archive.autodetection" value="none"/>
- </properties>
- </persistence-unit>
- <persistence-unit name="SimplePU">
- <jta-data-source>myDS</jta-data-source>
- <mapping-file>simple/Queries.xml</mapping-file>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.simple.Item</class>
- <class>org.jpwh.model.simple.User</class>
- <class>org.jpwh.model.simple.Bid</class>
- <class>org.jpwh.model.simple.Address</class>
- <class>org.jpwh.model.simple.Category</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- <properties>
- <!-- When remove(entity) is called, reset the identifier value of entity.
- so it's considered transient after removal -->
- <property name="hibernate.use_identifier_rollback" value="true"/>
- <!-- Enable this to try a custom table naming strategy
- <property name="hibernate.physical_naming_strategy"
- value="org.jpwh.shared.CENamingStrategy"/>
- -->
- </properties>
- </persistence-unit>
- <persistence-unit name="SimpleXMLCompletePU">
- <jta-data-source>myDS</jta-data-source>
- <mapping-file>simple/Mappings.xml</mapping-file>
- <mapping-file>simple/Queries.xml</mapping-file>
- <properties>
- <!-- Ignore hbm.xml files and annotated classes -->
- <property name="hibernate.archive.autodetection"
- value="none"/>
- </properties>
- </persistence-unit>
- <persistence-unit name="SimpleXMLOverridePU">
- <jta-data-source>myDS</jta-data-source>
- <mapping-file>simple/Queries.xml</mapping-file>
- <mapping-file>simple/MappingsOverride.xml</mapping-file>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.simple.Item</class>
- <class>org.jpwh.model.simple.User</class>
- <class>org.jpwh.model.simple.Bid</class>
- <class>org.jpwh.model.simple.Address</class>
- <class>org.jpwh.model.simple.Category</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SimpleXMLHibernatePU">
- <jta-data-source>myDS</jta-data-source>
- <properties>
- <!-- Only detect hbm.xml files, ignore annotations
- <property name="hibernate.archive.autodetection"
- value="hbm"/>
- -->
- <!-- But in our environment, we have many conflicting hbm.xml
- files, so we need to pick which ones we need in each unit test. -->
- <property name="hibernate.archive.autodetection"
- value="none"/>
- </properties>
- </persistence-unit>
- <persistence-unit name="ConverterPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.advanced.converter.Item</class>
- <class>org.jpwh.model.advanced.converter.User</class>
- <!--
- If automatic discovery/scanning is disabled, you have to
- add your @Converter classes here. In fact, to be compatible
- with Java SE, converter classes should always be listed here.
- -->
- <class>org.jpwh.converter.MonetaryAmountConverter</class>
- <class>org.jpwh.converter.ZipcodeConverter</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="UserTypePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <!-- For @TypeDefs in package-info.java -->
- <class>org.jpwh.converter</class>
- <class>org.jpwh.model.advanced.usertype.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MappedSuperclassPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.mappedsuperclass.BillingDetails</class>
- <class>org.jpwh.model.inheritance.mappedsuperclass.CreditCard</class>
- <class>org.jpwh.model.inheritance.mappedsuperclass.BankAccount</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="TablePerClassPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.tableperclass.BillingDetails</class>
- <class>org.jpwh.model.inheritance.tableperclass.CreditCard</class>
- <class>org.jpwh.model.inheritance.tableperclass.BankAccount</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SingleTablePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.singletable.BillingDetails</class>
- <class>org.jpwh.model.inheritance.singletable.CreditCard</class>
- <class>org.jpwh.model.inheritance.singletable.BankAccount</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="JoinedPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.joined.BillingDetails</class>
- <class>org.jpwh.model.inheritance.joined.CreditCard</class>
- <class>org.jpwh.model.inheritance.joined.BankAccount</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MixedPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.mixed.BillingDetails</class>
- <class>org.jpwh.model.inheritance.mixed.CreditCard</class>
- <class>org.jpwh.model.inheritance.mixed.BankAccount</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MixedFetchSelectPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="InheritanceEmbeddablePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.embeddable.Measurement</class>
- <class>org.jpwh.model.inheritance.embeddable.Dimensions</class>
- <class>org.jpwh.model.inheritance.embeddable.Weight</class>
- <class>org.jpwh.model.inheritance.embeddable.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="PolymorphicManyToOnePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.associations.manytoone.BillingDetails</class>
- <class>org.jpwh.model.inheritance.associations.manytoone.BankAccount</class>
- <class>org.jpwh.model.inheritance.associations.manytoone.CreditCard</class>
- <class>org.jpwh.model.inheritance.associations.manytoone.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="PolymorphicOneToManyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.inheritance.associations.onetomany.BillingDetails</class>
- <class>org.jpwh.model.inheritance.associations.onetomany.BankAccount</class>
- <class>org.jpwh.model.inheritance.associations.onetomany.CreditCard</class>
- <class>org.jpwh.model.inheritance.associations.onetomany.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="AdvancedPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.advanced.Item</class>
- <class>org.jpwh.model.advanced.Bid</class>
- <class>org.jpwh.model.advanced.User</class>
- <class>org.jpwh.model.advanced.Address</class>
- <class>org.jpwh.model.advanced.City</class>
- <class>org.jpwh.model.advanced.ItemBidSummary</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="CustomSchemaPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.complexschemas.custom.Bid</class>
- <class>org.jpwh.model.complexschemas.custom.Item</class>
- <class>org.jpwh.model.complexschemas.custom.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- <properties>
- <!--
- By default, Hibernate expects one SQL statement per line in scripts. This
- switches to the more convenient multi-line extractor. SQL statements in
- scripts are then terminated with semicolon. You can write your own
- <code>org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractor</code>
- implementation if you want to handle the SQL script in a different way.
- -->
- <property name="hibernate.hbm2ddl.import_files_sql_extractor"
- value="org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor"/>
- <!--
- This property defines when the create and drop scripts should be executed.
- Our custom SQL scripts will contain <code>CREATE DOMAIN</code> statements, which
- have to be executed before the tables using these domains are created. With
- these settings the schema generator will run the create script first, before
- reading your ORM metadata (annotations, XML files) and creating the tables.
- The drop script will execute after Hibernate drops the tables, giving us
- a chance to clean up anything we created. Other options are
- <code>metadata</code> (ignore custom script sources) and
- <code>script</code> (only use custom script source, ignore ORM metadata in
- annotations and XML files).
- -->
- <property name="javax.persistence.schema-generation.create-source"
- value="script-then-metadata"/>
- <property name="javax.persistence.schema-generation.drop-source"
- value="metadata-then-script"/>
- <!--
- The location of the custom SQL script for creation of the schema. The
- path is either (a) the location of the script resource on the classpath
- or (b) the location of the script as a <code>file://</code> URL or
- (c) if neither (a) or (b) match, the absolute or relative file path on
- the local file system. This example uses (a).
- -->
- <property name="javax.persistence.schema-generation.create-script-source"
- value="complexschemas/CreateScript.sql.txt"/>
- <!--
- The custom SQL script for dropping the schema.
- -->
- <property name="javax.persistence.schema-generation.drop-script-source"
- value="complexschemas/DropScript.sql.txt"/>
- <!--
- This load script runs after the tables have been created.
- -->
- <property name="javax.persistence.sql-load-script-source"
- value="complexschemas/LoadScript.sql.txt"/>
- </properties>
- </persistence-unit>
- <persistence-unit name="NaturalPrimaryKeyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model.complexschemas.naturalprimarykey.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="CompositeKeyEmbeddedIdPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model.complexschemas.compositekey.embedded.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="CompositeKeyMapsIdPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.complexschemas.compositekey.mapsid.User</class>
- <class>org.jpwh.model.complexschemas.compositekey.mapsid.Department</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="CompositeKeyReadOnlyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.complexschemas.compositekey.readonly.User</class>
- <class>org.jpwh.model.complexschemas.compositekey.readonly.Department</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="CompositeKeyManyToOnePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.complexschemas.compositekey.manytoone.User</class>
- <class>org.jpwh.model.complexschemas.compositekey.manytoone.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="NaturalForeignKeyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.complexschemas.naturalforeignkey.User</class>
- <class>org.jpwh.model.complexschemas.naturalforeignkey.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SecondaryTablePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.complexschemas.secondarytable.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="CustomSQLPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.customsql.Category</class>
- <class>org.jpwh.model.customsql.Bid</class>
- <class>org.jpwh.model.customsql.Item</class>
- <class>org.jpwh.model.customsql.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="CRUDProceduresPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.customsql.procedures.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SetOfStringsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.setofstrings.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="BagOfStringsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.bagofstrings.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ListOfStringsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.listofstrings.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MapOfStringsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.mapofstrings.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SortedSetOfStringsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.sortedsetofstrings.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SortedMapOfStringsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.sortedmapofstrings.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SetOfStringsOrderByPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.setofstringsorderby.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="BagOfStringsOrderByPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.bagofstringsorderby.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MapOfStringsOrderByPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.mapofstringsorderby.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SetOfEmbeddablesPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.setofembeddables.Item</class>
- <class>org.jpwh.model.collections.setofembeddables.Image</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="SetOfEmbeddablesOrderByPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.setofembeddablesorderby.Item</class>
- <class>org.jpwh.model.collections.setofembeddablesorderby.Image</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="BagOfEmbeddablesPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.bagofembeddables.Item</class>
- <class>org.jpwh.model.collections.bagofembeddables.Image</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MapOfStringsEmbeddablesPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.mapofstringsembeddables.Item</class>
- <class>org.jpwh.model.collections.mapofstringsembeddables.Image</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MapOfEmbeddablesPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.mapofembeddables.Item</class>
- <class>org.jpwh.model.collections.mapofembeddables.Image</class>
- <class>org.jpwh.model.collections.mapofembeddables.Filename</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="EmbeddableSetOfStringsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.collections.embeddablesetofstrings.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyBidirectionalPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.bidirectional.Item</class>
- <class>org.jpwh.model.associations.onetomany.bidirectional.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyCascadePersistPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.cascadepersist.Item</class>
- <class>org.jpwh.model.associations.onetomany.cascadepersist.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyCascadeRemovePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.cascaderemove.Item</class>
- <class>org.jpwh.model.associations.onetomany.cascaderemove.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyOrphanRemovalPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.orphanremoval.Item</class>
- <class>org.jpwh.model.associations.onetomany.orphanremoval.Bid</class>
- <class>org.jpwh.model.associations.onetomany.orphanremoval.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyOnDeleteCascadePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.ondeletecascade.Item</class>
- <class>org.jpwh.model.associations.onetomany.ondeletecascade.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyBagPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.bag.Item</class>
- <class>org.jpwh.model.associations.onetomany.bag.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyListPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.list.Item</class>
- <class>org.jpwh.model.associations.onetomany.list.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyJoinTablePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.jointable.Item</class>
- <class>org.jpwh.model.associations.onetomany.jointable.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyEmbeddablePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.embeddable.User</class>
- <class>org.jpwh.model.associations.onetomany.embeddable.Shipment</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToManyEmbeddableJoinTablePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetomany.embeddablejointable.User</class>
- <class>org.jpwh.model.associations.onetomany.embeddablejointable.Shipment</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToOneSharedPrimaryKeyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetoone.sharedprimarykey.User</class>
- <class>org.jpwh.model.associations.onetoone.sharedprimarykey.Address</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToOneForeignGeneratorPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetoone.foreigngenerator.User</class>
- <class>org.jpwh.model.associations.onetoone.foreigngenerator.Address</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToOneForeignKeyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetoone.foreignkey.User</class>
- <class>org.jpwh.model.associations.onetoone.foreignkey.Address</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="OneToOneJoinTablePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.onetoone.jointable.Item</class>
- <class>org.jpwh.model.associations.onetoone.jointable.Shipment</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ManyToManyBidirectionalPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.manytomany.bidirectional.Category</class>
- <class>org.jpwh.model.associations.manytomany.bidirectional.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ManyToManyLinkEntityPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.manytomany.linkentity.Category</class>
- <class>org.jpwh.model.associations.manytomany.linkentity.Item</class>
- <class>org.jpwh.model.associations.manytomany.linkentity.CategorizedItem</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ManyToManyTernaryPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.manytomany.ternary.Category</class>
- <class>org.jpwh.model.associations.manytomany.ternary.Item</class>
- <class>org.jpwh.model.associations.manytomany.ternary.User</class>
- <class>org.jpwh.model.associations.manytomany.ternary.CategorizedItem</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MapsMapKeyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.maps.mapkey.Item</class>
- <class>org.jpwh.model.associations.maps.mapkey.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="MapsTernaryPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.associations.maps.ternary.Item</class>
- <class>org.jpwh.model.associations.maps.ternary.Category</class>
- <class>org.jpwh.model.associations.maps.ternary.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ConcurrencyVersioningPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.concurrency.version.Item</class>
- <class>org.jpwh.model.concurrency.version.Bid</class>
- <class>org.jpwh.model.concurrency.version.Category</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ConcurrencyVersioningTimestampPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.concurrency.versiontimestamp.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ConcurrencyVersioningAllPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.concurrency.versionall.Item</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="ConversationPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.conversation.User</class>
- <class>org.jpwh.model.conversation.Item</class>
- <class>org.jpwh.model.conversation.Image</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FilteringCascadePU">
- <jta-data-source>myDS</jta-data-source>
- <mapping-file>filtering/DefaultCascadePersist.xml</mapping-file>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.filtering.cascade.Item</class>
- <class>org.jpwh.model.filtering.cascade.Bid</class>
- <class>org.jpwh.model.filtering.cascade.User</class>
- <class>org.jpwh.model.filtering.cascade.BillingDetails</class>
- <class>org.jpwh.model.filtering.cascade.CreditCard</class>
- <class>org.jpwh.model.filtering.cascade.BankAccount</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FilteringCallbackPU">
- <jta-data-source>myDS</jta-data-source>
- <mapping-file>filtering/EventListeners.xml</mapping-file>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.filtering.callback.Item</class>
- <class>org.jpwh.model.filtering.callback.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FilteringInterceptorPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.filtering.interceptor.Item</class>
- <class>org.jpwh.model.filtering.interceptor.User</class>
- <class>org.jpwh.model.filtering.interceptor.AuditLogRecord</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- <properties>
- <property name="hibernate.ejb.event.load"
- value="org.jpwh.test.filtering.SecurityLoadListener"/>
- </properties>
- </persistence-unit>
- <persistence-unit name="FilteringEnversPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.filtering.envers.Item</class>
- <class>org.jpwh.model.filtering.envers.User</class>
- <class>org.jpwh.model.filtering.envers.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FilteringDynamicPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.filtering.dynamic</class>
- <class>org.jpwh.model.filtering.dynamic.User</class>
- <class>org.jpwh.model.filtering.dynamic.Item</class>
- <class>org.jpwh.model.filtering.dynamic.Category</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="QueryingPU">
- <jta-data-source>myDS</jta-data-source>
- <mapping-file>querying/ExternalizedQueries.xml</mapping-file>
- <mapping-file>querying/Selection.xml</mapping-file>
- <mapping-file>querying/Restriction.xml</mapping-file>
- <mapping-file>querying/Projection.xml</mapping-file>
- <mapping-file>querying/Joins.xml</mapping-file>
- <mapping-file>querying/Grouping.xml</mapping-file>
- <mapping-file>querying/Subselects.xml</mapping-file>
- <mapping-file>querying/NativeQueries.xml</mapping-file>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.querying</class>
- <class>org.jpwh.model.querying.Category</class>
- <class>org.jpwh.model.querying.Item</class>
- <class>org.jpwh.model.querying.Bid</class>
- <class>org.jpwh.model.querying.Image</class>
- <class>org.jpwh.model.querying.User</class>
- <class>org.jpwh.model.querying.Address</class>
- <class>org.jpwh.model.querying.LogRecord</class>
- <class>org.jpwh.model.inheritance.tableperclass.BillingDetails</class>
- <class>org.jpwh.model.inheritance.tableperclass.CreditCard</class>
- <class>org.jpwh.model.inheritance.tableperclass.BankAccount</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- <properties>
- <!-- You typically want portable, predictable sorting for nulls in your app -->
- <property name="hibernate.order_by.default_null_ordering" value="first"/>
- </properties>
- </persistence-unit>
- <persistence-unit name="FetchingProxyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.proxy.Category</class>
- <class>org.jpwh.model.fetching.proxy.Item</class>
- <class>org.jpwh.model.fetching.proxy.Bid</class>
- <class>org.jpwh.model.fetching.proxy.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingInterceptionPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.interception.Item</class>
- <class>org.jpwh.model.fetching.interception.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingEagerJoinPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.eagerjoin.Item</class>
- <class>org.jpwh.model.fetching.eagerjoin.User</class>
- <class>org.jpwh.model.fetching.eagerjoin.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingNPlusOneSelectsPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.nplusoneselects.Item</class>
- <class>org.jpwh.model.fetching.nplusoneselects.User</class>
- <class>org.jpwh.model.fetching.nplusoneselects.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingCartesianProductPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.cartesianproduct.Item</class>
- <class>org.jpwh.model.fetching.cartesianproduct.User</class>
- <class>org.jpwh.model.fetching.cartesianproduct.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingBatchPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.batch.Item</class>
- <class>org.jpwh.model.fetching.batch.User</class>
- <class>org.jpwh.model.fetching.batch.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingSubselectPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.subselect.Item</class>
- <class>org.jpwh.model.fetching.subselect.User</class>
- <class>org.jpwh.model.fetching.subselect.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingEagerSelectPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.eagerselect.Item</class>
- <class>org.jpwh.model.fetching.eagerselect.User</class>
- <class>org.jpwh.model.fetching.eagerselect.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingProfilePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.profile</class>
- <class>org.jpwh.model.fetching.profile.Item</class>
- <class>org.jpwh.model.fetching.profile.User</class>
- <class>org.jpwh.model.fetching.profile.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingReadOnlyPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.readonly.Item</class>
- <class>org.jpwh.model.fetching.readonly.User</class>
- <class>org.jpwh.model.fetching.readonly.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="FetchingFetchLoadGraphPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.fetching.fetchloadgraph.Item</class>
- <class>org.jpwh.model.fetching.fetchloadgraph.User</class>
- <class>org.jpwh.model.fetching.fetchloadgraph.Bid</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
- <persistence-unit name="BulkBatchPU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model.bulkbatch</class>
- <!-- Note the special ID generator in this package -->
- <class>org.jpwh.model.bulkbatch.Item</class>
- <class>org.jpwh.model.bulkbatch.User</class>
- <class>org.jpwh.model.bulkbatch.Bid</class>
- <class>org.jpwh.model.bulkbatch.BillingDetails</class>
- <class>org.jpwh.model.bulkbatch.CreditCard</class>
- <class>org.jpwh.model.bulkbatch.BankAccount</class>
- <class>org.jpwh.model.bulkbatch.StolenCreditCard</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- <properties>
- <property name="hibernate.jdbc.batch_size" value="100"/>
- <property name="hibernate.jdbc.batch_versioned_data" value="true"/>
- <property name="hibernate.order_inserts" value="true"/>
- </properties>
- </persistence-unit>
- <persistence-unit name="CachePU">
- <jta-data-source>myDS</jta-data-source>
- <class>org.jpwh.model</class>
- <class>org.jpwh.model.cache.Item</class>
- <class>org.jpwh.model.cache.Bid</class>
- <class>org.jpwh.model.cache.User</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- <!--
- The shared cache mode controls how entity classes of this persistence
- unit become cacheable. Usually you prefer to enable caching selectively
- for only some entity classes. Other options are
- <code>DISABLE_SELECTIVE</code>, <code>ALL</code>, and <code>NONE</code>.
- -->
- <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
- <properties>
- <!--
- Hibernate's second-level cache system has to be enabled
- explicitly, as it is not enabled by default. You can separately
- enable the query result cache; it's disabled by default as well.
- -->
- <property name="hibernate.cache.use_second_level_cache"
- value="true"/>
- <property name="hibernate.cache.use_query_cache"
- value="true"/>
- <!--
- Next, you pick a provider for the second-level cache system. For EHCache,
- add the <code>org.hibernate:hibernate-ehcache</code> Maven artifact
- dependency to your classpath. Then, pick how Hibernate uses EHCache with this
- region factory setting; here we tell Hibernate to manage a single
- EHCache instance internally as the second-level cache provider.
- -->
- <property name="hibernate.cache.region.factory_class"
- value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
- <!--
- Hibernate will pass this property along to EHCache when the provider
- is started, setting the location of the EHCache configuration file. All
- physical cache settings for cache regions are in this file.
- -->
- <property name="net.sf.ehcache.configurationResourceName"
- value="/cache/ehcache.xml"/>
- <!--
- This setting controls how Hibernate disassembles and assembles
- entity state when data is stored and loaded from the second-level
- cache. The "structured" cache entry format is less efficient but
- necessary in a clustered environment. For a non-clustered
- second-level cache, like our singleton EHCache on this JVM, you
- can disable this setting and a more efficient format is used.
- -->
- <property name="hibernate.cache.use_structured_entries"
- value="false"/>
- <!--
- While you experiment with the second-level cache, you usually
- want to see and examine what's happening behind the scenes. Hibernate
- has a statistics collector and an API to access these statistics. For
- performance reasons, it is disabled by default (and should be
- disabled in production).
- -->
- <property name="hibernate.generate_statistics"
- value="true"/>
- </properties>
- </persistence-unit>
- </persistence>
For the “Hello World” application, you delegate database connection handling to a Java Transaction API ( JTA ) provider, the open source Bitronix project. Bitronix offers connection pooling with a managed java.sql.DataSource and the standard javax.transaction.UserTransaction API in any Java SE environment. Bitronix binds
these objects into JNDI , and Hibernate interfaces automatically with Bitronix through JNDI lookups.
2.jndi.properties(这个文件似乎不起作用)
# Bitronix has a built-in JNDI context, for binding and looking up datasources
java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory
四、测试文件
1.
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 { @Test
public void storeLoadMessage() throws Exception { EntityManagerFactory emf =
Persistence.createEntityManagerFactory("HelloWorldPU"); try {
{
/*
Get access to the standard transaction API <code>UserTransaction</code> and
begin a transaction on this thread of execution.
*/
UserTransaction tx = TM.getUserTransaction();
tx.begin(); /*
Begin a new session with the database by creating an <code>EntityManager</code>, this
is your context for all persistence operations.
*/
EntityManager em = emf.createEntityManager(); /*
Create a new instance of the mapped domain model class <code>Message</code> and
set its <code>text</code> property.
*/
Message message = new Message();
message.setText("Hello World!"); /*
Enlist the transient instance with your persistence context, you make it persistent.
Hibernate now knows that you wish to store that data, it doesn't necessarily call the
database immediately, however.
*/
em.persist(message); /*
Commit the transaction, Hibernate now automatically checks the persistence context and
executes the necessary SQL <code>INSERT</code> statement.
*/
tx.commit();
// INSERT into MESSAGE (ID, TEXT) values (1, 'Hello World!') /*
If you create an <code>EntityManager</code>, you must close it.
*/
em.close();
} {
/*
Every interaction with your database should occur within explicit transaction boundaries,
even if you are only reading data.
*/
UserTransaction tx = TM.getUserTransaction();
tx.begin(); EntityManager em = emf.createEntityManager(); /*
Execute a query to retrieve all instances of <code>Message</code> from the database.
*/
List<Message> messages =
em.createQuery("select m from Message m").getResultList();
// SELECT * from MESSAGE assertEquals(messages.size(), 1);
assertEquals(messages.get(0).getText(), "Hello World!"); /*
You can change the value of a property, Hibernate will detect this automatically because
the loaded <code>Message</code> is still attached to the persistence context it was loaded in.
*/
messages.get(0).setText("Take me to your leader!"); /*
On commit, Hibernate checks the persistence context for dirty state and executes the
SQL <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 = 1 em.close();
} } finally {
TM.rollback();
emf.close();
}
} }
2.
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() { /*
This builder helps you create the immutable service registry with
chained method calls.
*/
StandardServiceRegistryBuilder serviceRegistryBuilder =
new StandardServiceRegistryBuilder(); /*
Configure the services registry by applying settings.
*/
serviceRegistryBuilder
.applySetting("hibernate.connection.datasource", "myDS")
.applySetting("hibernate.format_sql", "true")
.applySetting("hibernate.use_sql_comments", "true")
.applySetting("hibernate.hbm2ddl.auto", "update"); //create-drop // Enable JTA (this is a bit crude because Hibernate devs still believe that JTA is
// used only in monstrous application servers and you'll never see this code).
serviceRegistryBuilder.applySetting(
Environment.TRANSACTION_COORDINATOR_STRATEGY,
JtaTransactionCoordinatorBuilderImpl.class
);
ServiceRegistry serviceRegistry = serviceRegistryBuilder.build(); /*
You can only enter this configuration stage with an existing service registry.
*/
MetadataSources metadataSources = new MetadataSources(serviceRegistry); /*
Add your persistent classes to the (mapping) metadata sources.
*/
metadataSources.addAnnotatedClass(
org.jpwh.model.helloworld.Message.class
); // Add hbm.xml mapping files
// metadataSources.addFile(...); // Read all hbm.xml mapping files from a JAR
// metadataSources.addJar(...) MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder(); Metadata metadata = metadataBuilder.build(); assertEquals(metadata.getEntityBindings().size(), 1); SessionFactory sessionFactory = metadata.buildSessionFactory(); return sessionFactory;
} @Test
public void storeLoadMessage() throws Exception {
SessionFactory sessionFactory = createSessionFactory();
try {
{
/*
Get access to the standard transaction API <code>UserTransaction</code> and
begin a transaction on this thread of execution.
*/
UserTransaction tx = TM.getUserTransaction();
tx.begin(); /*
Whenever you call <code>getCurrentSession()</code> in the same thread you get
the same <code>org.hibernate.Session</code>. It's bound automatically to the
ongoing transaction and is closed for you automatically when that transaction
commits or rolls back.
*/
Session session = sessionFactory.getCurrentSession(); Message message = new Message();
message.setText("Hello World!"); /*
The native Hibernate API is very similar to the standard Java Persistence API and most methods
have the same name.
*/
session.persist(message); /*
Hibernate synchronizes the session with the database and closes the "current"
session on commit of the bound transaction automatically.
*/
tx.commit();
// INSERT into MESSAGE (ID, TEXT) values (1, 'Hello World!')
} {
UserTransaction tx = TM.getUserTransaction();
tx.begin(); /*
A Hibernate criteria query is a type-safe programmatic way to express queries,
automatically translated into SQL.
*/
List<Message> messages =
sessionFactory.getCurrentSession().createCriteria(
Message.class
).list();
// SELECT * from MESSAGE //assertEquals(messages.size(), 1);
assertEquals(messages.get(0).getText(), "Hello World!"); tx.commit();
} } finally {
TM.rollback();
}
}
}
3.
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; /**
* Starts and stops the transaction manager/database pool before/after a test suite.
* <p>
* All tests in a suite execute with a single {@link TransactionManagerSetup}, call
* the static {@link TransactionManagerTest#TM} in your test to access the JTA
* transaction manager and database connections.
* </p>
* <p>
* The test parameters <code>database</code> (specifying a supported
* {@link DatabaseProduct}) and a <code>connectionURL</code> are optional.
* The default is an in-memory H2 database instance, created and destroyed
* automatically for each test suite.
* </p>
*/
public class TransactionManagerTest { // Static single database connection manager per test suite
static public TransactionManagerSetup TM; @Parameters({"database", "connectionURL"})
@BeforeSuite()
public void beforeSuite(@Optional String database,
@Optional String connectionURL) throws Exception {
database = "mysql";
TM = new TransactionManagerSetup(
database != null
? DatabaseProduct.valueOf(database.toUpperCase(Locale.US))
: DatabaseProduct.H2,
connectionURL
);
} @AfterSuite(alwaysRun = true)
public void afterSuite() throws Exception {
if (TM != null)
TM.stop();
}
}
4.
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; /**
* Provides a database connection pool with the Bitronix JTA transaction
* manager (http://docs.codehaus.org/display/BTM/Home).
* <p>
* Hibernate will look up the datasource and <code>UserTransaction</code> through
* JNDI, that's why you also need a <code>jndi.properties</code> file. A minimal
* JNDI context is bundled with and started by 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); // Our locking/versioning tests assume READ COMMITTED transaction
// isolation. This is not the default on MySQL InnoDB, so we set
// it here explicitly.
datasource.setIsolationLevel("READ_COMMITTED"); // Hibernate's SQL schema generator calls connection.setAutoCommit(true)
// and we use auto-commit mode when the EntityManager is in suspended
// mode and not joined with a transaction.
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();
} }
5.
package org.jpwh.env; import bitronix.tm.resource.jdbc.PoolingDataSource; import java.util.Properties; public enum DatabaseProduct { H2(
new DataSourceConfiguration() {
@Override
public void configure(PoolingDataSource ds, String connectionURL) {
ds.setClassName("org.h2.jdbcx.JdbcDataSource"); // External instance: jdbc:h2:tcp://localhost/mem:test;USER=sa
ds.getDriverProperties().put(
"URL",
connectionURL != null
? connectionURL :
"jdbc:h2:mem:test"
); // TODO: http://code.google.com/p/h2database/issues/detail?id=502
ds.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() {
@Override
public 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/10174951
Properties connectionProperties = new Properties();
connectionProperties.put("useFetchSizeWithLongColumn", "true");
ds.getDriverProperties().put("connectionProperties", connectionProperties);
}
},
org.hibernate.dialect.Oracle10gDialect.class.getName()
), POSTGRESQL(
new DataSourceConfiguration() {
@Override
public 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() {
@Override
public 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");
ds.getDriverProperties().put("user", "root");
ds.getDriverProperties().put("password", "1234");
}
},
// Yes, this should work with 5.6, no idea why Gail named it 5.7
org.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);
} }
JavaPersistenceWithHibernate第二版笔记Getting started with ORM-001用JPA和Hibernate实现HellowWorld(JTA、Bitronix)的更多相关文章
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-006Mixing inheritance strategies(@SecondaryTable、@PrimaryKeyJoinColumn、<join fetch="select">)
一.结构 For example, you can map a class hierarchy to a single table, but, for a particular subclass, s ...
- JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-003映射实体时的可选操作(<delimited-identifiers/>、PhysicalNamingStrategy、PhysicalNamingStrategyStandardImpl、、、)
一.自定义映射的表名 1. @Entity @Table(name = "USERS") public class User implements Serializable { / ...
- JavaPersistenceWithHibernate第二版笔记Getting started with ORM-002Domain层详解及M etaModel
一.结构 二.配置文件约定 The JPA provider automatically picks up this descriptor if you place it in a META-INF ...
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-003Table per concrete class with unions(@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)、<union-subclass>)
一.代码 1. package org.jpwh.model.inheritance.tableperclass; import org.jpwh.model.Constants; import ja ...
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-002Table per concrete class with implicit polymorphism(@MappedSuperclass、@AttributeOverride)
一.结构 二.代码 1. package org.jpwh.model.inheritance.mappedsuperclass; import javax.persistence.MappedSup ...
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-001Hibernate映射继承的方法
There are four different strategies for representing an inheritance hierarchy: Use one table per co ...
- JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-007UserTypes的用法(@org.hibernate.annotations.Type、@org.hibernate.annotations.TypeDefs、CompositeUserType、DynamicParameterizedType、、、)
一.结构 二.Hibernate支持的UserTypes接口 UserType —You can transform values by interacting with the plain JD ...
- JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-006类型转换器( @Converter(autoApply = true) 、type="converter:qualified.ConverterName" )
一.结构 二.代码 1. package org.jpwh.model.advanced; import java.io.Serializable; import java.math.BigDecim ...
- JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-005控制类型映射(Nationalized、@LOB、@org.hibernate.annotations.Type)
一.简介 1. 2. 3. 4. to override this default mapping. The JPA specification has a convenient shortcut a ...
随机推荐
- QT 十六进制整数变为字符串自动补0 && 十进制补零
QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')); int a=0001; QStri ...
- [DHCP服务]——DHCP详解
DHCP:(Dynamic Host Configuration Protocol) 动态主机配置协议 1. DHCP是一个局域网的网络协议,采用UDP协议工作 2. DHCP作用 (1)主要应用在大 ...
- Careercup - Microsoft面试题 - 5943729928011776
2014-05-10 21:56 题目链接 原题: Suppose you get number of unique users every second from bing For eg, ,,,, ...
- Entity Framework技术导游系列开篇与热身
在微软平台写程序有年头了,随着微软数据存取技术的持续演化,我在程序中先后使用过ODBC.DAO.ADO.ADO.NET.LINQ to SQL. Entity Framework这些技术. 近几年来, ...
- 【BZOJ】【3907】网格
组合数学/python 3907: 网格 Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 162 Solved: 76[Submit][Status][ ...
- 【BZOJ】【2424】【HAOI2010】订货
网络流/费用流 比较简单的题……我一开始想成像软件开发那题一样的做法了……就是每天拆点,S->i (INF,0) .i+n->T (u[i],0) 然后处理购入 S->i+n (IN ...
- poi过滤操作后产生新的sheet
public Sheet filterSheet(Sheet sheetToFilter){ if(sheetToFilter == null){ System.out.println("s ...
- sampleGradient(sampler,uv,dds,ddy)
vsm里面用这个梯度采样 采放了z,z*z的shadowmap 这种采样方式和普通sample有什么区别
- Python中__init__方法/__name__系统变量讲解
__init__方法在类的一个对象被建立时,马上运行.这个方法可以用来对你的对象做一些你希望的初始化. 代码例子 test.py#!/usr/bin/python# Filename: class_i ...
- Guid和Int还有Double、Date的ToString方法的常见格式
Guid的常见格式: 1.Guid.NewGuid().ToString("N") 结果为: 38bddf48f43c48588e0d78761eaa1ce6 2.Gu ...