Hibernate example source code file (transactions.po)
This example Hibernate source code file (transactions.po) is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.
Java - Hibernate tags/keywords
cmt, ejb, hibernate, hibernate, in, jdbc, jta, jta, session, tag, tag, the, the, this
The Hibernate transactions.po source code
# translation of Collection_Mapping.po to
# Xi Huang <xhuang@redhat.com>, 2006.
# Xi HUANG <xhuang@redhat.com>, 2007.
msgid ""
msgstr ""
"Project-Id-Version: Collection_Mapping\n"
"Report-Msgid-Bugs-To: http://bugs.kde.org\n"
"POT-Creation-Date: 2010-02-11T05:38:16\n"
"PO-Revision-Date: 2010-03-16 09:58+1000\n"
"Last-Translator: Xi HUANG <xhuang@redhat.com>\n"
"Language-Team: <en@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
#. Tag: title
#, no-c-format
msgid "Transactions and Concurrency"
msgstr "事务和并发 "
#. Tag: para
#, no-c-format
msgid "The most important point about Hibernate and concurrency control is that it is easy to understand. Hibernate directly uses JDBC connections and JTA resources without adding any additional locking behavior. It is recommended that you spend some time with the JDBC, ANSI, and transaction isolation specification of your database management system."
msgstr "Hibernate 的事务和并发控制很容易掌握。Hibernate 直接使用 JDBC 连接和 JTA 资源,不添加任何附加锁定行为。我们强烈推荐你花点时间了解 JDBC 编程,ANSI SQL 查询语言和你使用的数据库系统的事务隔离规范。 "
#. Tag: para
#, no-c-format
msgid "Hibernate does not lock objects in memory. Your application can expect the behavior as defined by the isolation level of your database transactions. Through <literal>Session, which is also a transaction-scoped cache, Hibernate provides repeatable reads for lookup by identifier and entity queries and not reporting queries that return scalar values."
msgstr "Hibernate 不锁定内存中的对象。你的应用程序会按照你的数据库事务的隔离级别规定的那样运作。幸亏有了 <literal>Session,使得 Hibernate 通过标识符查找,和实体查询(不是返回标量值的报表查询)提供了可重复的读取(Repeatable reads)功能,Session 同时也是事务范围内的缓存(cache)。 "
#. Tag: para
#, no-c-format
msgid "In addition to versioning for automatic optimistic concurrency control, Hibernate also offers, using the <literal>SELECT FOR UPDATE syntax, a (minor) API for pessimistic locking of rows. Optimistic concurrency control and this API are discussed later in this chapter."
msgstr "除了对自动乐观并发控制提供版本管理,针对行级悲观锁定,Hibernate 也提供了辅助的(较小的)API,它使用了 <literal>SELECT FOR UPDATE 的 SQL 语法。本章后面会讨论乐观并发控制和这个API。 "
#. Tag: para
#, no-c-format
msgid "The discussion of concurrency control in Hibernate begins with the granularity of <literal>Configuration, SessionFactory, and Session, as well as database transactions and long conversations."
msgstr "我们从 <literal>Configuration层、SessionFactory 层,和 Session 层开始讨论 Hibernate 的并行控制、数据库事务和应用程序的长事务。 "
#. Tag: title
#, no-c-format
msgid "Session and transaction scopes"
msgstr "Session 和事务范围(transaction scope)"
#. Tag: para
#, no-c-format
msgid "A <literal>SessionFactory is an expensive-to-create, threadsafe object, intended to be shared by all application threads. It is created once, usually on application startup, from a Configuration instance."
msgstr "<literal>SessionFactory 对象的创建代价很昂贵,它是线程安全的对象,它为所有的应用程序线程所共享。它只创建一次,通常是在应用程序启动的时候,由一个 Configuraion 的实例来创建。 "
#. Tag: para
#, no-c-format
msgid "A <literal>Session is an inexpensive, non-threadsafe object that should be used once and then discarded for: a single request, a conversation or a single unit of work. A Session will not obtain a JDBC Connection, or a Datasource, unless it is needed. It will not consume any resources until used."
msgstr "<literal>Session 对象的创建代价比较小,是非线程安全的,对于单个请求,单个会话、单个的 工作单元而言,它只被使用一次,然后就丢弃。只有在需要的时候,一个 Session 对象 才会获取一个 JDBC 的 Connection(或一个Datasource)对象,因此假若不使用的时候它不消费任何资源。 "
#. Tag: para
#, no-c-format
msgid "In order to reduce lock contention in the database, a database transaction has to be as short as possible. Long database transactions will prevent your application from scaling to a highly concurrent load. It is not recommended that you hold a database transaction open during user think time until the unit of work is complete."
msgstr "此外我们还要考虑数据库事务。数据库事务应该尽可能的短,降低数据库中的锁争用。数据库长事务会阻止你的应用程序扩展到高的并发负载。因此,假若在用户思考期间让数据库事务开着,直到整个工作单元完成才关闭这个事务,这绝不是一个好的设计。 "
#. Tag: para
#, no-c-format
msgid "What is the scope of a unit of work? Can a single Hibernate <literal>Session span several database transactions, or is this a one-to-one relationship of scopes? When should you open and close a Session and how do you demarcate the database transaction boundaries? These questions are addressed in the following sections."
msgstr "一个操作单元(Unit of work)的范围是多大?单个的 Hibernate <literal>Session 能跨越多个数据库事务吗?还是一个 Session 的作用范围对应一个数据库事务的范围?应该何时打开 Session,何时关闭 Session,你又如何划分数据库事务的边界呢?我们将在后续章节解决这些问题。"
#. Tag: title
#, no-c-format
msgid "Unit of work"
msgstr "操作单元(Unit of work)"
#. Tag: para
#, no-c-format
msgid "First, let's define a unit of work. A unit of work is a design pattern described by Martin Fowler as <quote> [maintaining] a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. PoEAA In other words, its a series of operations we wish to carry out against the database together. Basically, it is a transaction, though fulfilling a unit of work will often span multiple physical database transactions (see ). So really we are talking about a more abstract notion of a transaction. The term \"business transaction\" is also sometimes used in lieu of unit of work."
msgstr "首先,让我们定义一个工作单元(unit of work)。工作单元是一个设计模式,Martin Fowler 把它描述为 <quote> [maintaining] a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. PoEAA 换句话说,它是我们希望对数据库执行的一系列操作。基本上,它是一个事务,虽然完成一个工作单元经常将跨越多个物理数据库事务(请参考 )。所以,实际上我们在讨论一个更抽象的事务概念。术语 \"business transaction\" 有时也和工作单元一起使用。"
#. Tag: para
#, no-c-format
msgid "Do not use the <emphasis>session-per-operation antipattern: do not open and close a Session for every simple database call in a single thread. The same is true for database transactions. Database calls in an application are made using a planned sequence; they are grouped into atomic units of work. This also means that auto-commit after every single SQL statement is useless in an application as this mode is intended for ad-hoc SQL console work. Hibernate disables, or expects the application server to disable, auto-commit mode immediately. Database transactions are never optional. All communication with a database has to occur inside a transaction. Auto-commit behavior for reading data should be avoided, as many small transactions are unlikely to perform better than one clearly defined unit of work. The latter is also more maintainable and extensible."
msgstr "首先,别用 <emphasis>session-per-operation 这种反模式了,也就是说,在单个线程中, 不要因为一次简单的数据库调用,就打开和关闭一次 Session!数据库事务也是如此。 应用程序中的数据库调用是按照计划好的次序,分组为原子的操作单元。(注意,这也意味着,应用程 序中,在单个的 SQL 语句发送之后,自动事务提交(auto-commit)模式失效了。这种模式专门为SQL控制台操作设计的。 Hibernate 禁止立即自动事务提交模式,或者期望应用服务器禁止立即自动事务提交模式。)数据库事务绝不是可有可无的,任何与数据库之间的通讯都必须在某个事务中进行,不管你是在读还是在写数据。对读数据而言,应该避免 auto-commit 行为,因为很多小的事务比一个清晰定义的工作单元性能差。后者也更容易维护和扩展。 "
#. Tag: para
#, no-c-format
msgid "The most common pattern in a multi-user client/server application is <emphasis>session-per-request. In this model, a request from the client is sent to the server, where the Hibernate persistence layer runs. A new Hibernate Session is opened, and all database operations are executed in this unit of work. On completion of the work, and once the response for the client has been prepared, the session is flushed and closed. Use a single database transaction to serve the clients request, starting and committing it when you open and close the Session. The relationship between the two is one-to-one and this model is a perfect fit for many applications."
msgstr "在多用户的 client/server 应用程序中,最常用的模式是 <emphasis>每个请求一个会话(session-per-request)。 在这种模式下,来自客户端的请求被发送到服务器端(即 Hibernate 持久化层运行的地方),一个新的 Hibernate Session 被打开,并且执行这个操作单元中所有的数据库操作。一旦操作完成(同时对客户端的响应也准备就绪),session 被同步,然后关闭。你也可以使用单 个数据库事务来处理客户端请求,在你打开 Session 之后启动事务,在你关闭 Session 之前提交事务。会话和请求之间的关系是一对一的关系,这种模式对 于大多数应用程序来说是很棒的。 "
#. Tag: para
#, no-c-format
msgid "The challenge lies in the implementation. Hibernate provides built-in management of the \"current session\" to simplify this pattern. Start a transaction when a server request has to be processed, and end the transaction before the response is sent to the client. Common solutions are <literal>ServletFilter, AOP interceptor with a pointcut on the service methods, or a proxy/interception container. An EJB container is a standardized way to implement cross-cutting aspects such as transaction demarcation on EJB session beans, declaratively with CMT. If you use programmatic transaction demarcation, for ease of use and code portability use the Hibernate Transaction API shown later in this chapter."
msgstr "实现才是真正的挑战。Hibernate 内置了对\"当前 session(current session)\" 的管理,用于简化此模式。你要做的一切就是在服务器端要处理请求的时候,开启事务,在响应发送给客户之前结束事务。你可以用任何方式来完成这一操作,通常的方案有 <literal>ServletFilter,在 service 方法中进行 pointcut 的 AOP 拦截器,或者 proxy/interception 容器。EJB 容器是实现横切诸如 EJB session bean 上的事务分界,用 CMT 对事务进行声明等方面的标准手段。假若你决定使用编程式的事务分界,请参考本章后面讲到的 Hibernate Transaction API,这对易用性和代码可移植性都有好处。 "
#. Tag: para
#, no-c-format
msgid "Your application code can access a \"current session\" to process the request by calling <literal>sessionFactory.getCurrentSession(). You will always get a Session scoped to the current database transaction. This has to be configured for either resource-local or JTA environments, see ."
msgstr "在任何时间,任何地方,你的应用代码可以通过简单的调用<literal>sessionFactory.getCurrentSession() 来访问\"当前 session\",用于处理请求。你总是会得到当前数据库事务范围内的 Session。在使用本地资源或 JTA 环境时,必须配置它,请参见 。"
#. Tag: para
#, no-c-format
msgid "You can extend the scope of a <literal>Session and database transaction until the \"view has been rendered\". This is especially useful in servlet applications that utilize a separate rendering phase after the request has been processed. Extending the database transaction until view rendering, is achieved by implementing your own interceptor. However, this will be difficult if you rely on EJBs with container-managed transactions. A transaction will be completed when an EJB method returns, before rendering of any view can start. See the Hibernate website and forum for tips and examples relating to this Open Session in View pattern."
msgstr "有时,将 <literal>Session 和数据库事务的边界延伸到\"展示层被渲染后\"会带来便利。有些 serlvet 应用程序在对请求进行处理后,有个单独的渲染期,这种延伸对这种程序特别有用。假若你实现你自己的拦截器,把事务边界延伸到展示层渲染结束后非常容易。然而,假若你依赖有容器管理事务的 EJB,这就不太容易了,因为事务会在 EJB 方法返回后结束,而那是在任何展示层渲染开始之前。请访问 Hibernate 网站和论坛,你可以找到 Open Session in View 这一模式的提示和示例。 "
#. Tag: title
#, no-c-format
msgid "Long conversations"
msgstr "长对话"
#. Tag: para
#, no-c-format
msgid "The session-per-request pattern is not the only way of designing units of work. Many business processes require a whole series of interactions with the user that are interleaved with database accesses. In web and enterprise applications, it is not acceptable for a database transaction to span a user interaction. Consider the following example:"
msgstr "session-per-request 模式不仅仅是一个可以用来设计操作单元的有用概念。很多业务处理都需 要一系列完整的与用户之间的交互,而这些用户是指对数据库有交叉访问的用户。在基于 web 的应用和企业应用中,跨用户交互的数据库事务是无法接受的。考虑下面的例子: "
#. Tag: para
#, no-c-format
msgid "The first screen of a dialog opens. The data seen by the user has been loaded in a particular <literal>Session and database transaction. The user is free to modify the objects."
msgstr "在界面的第一屏,打开对话框,用户所看到的数据是被一个特定的 <literal>Session 和数据 库事务载入(load)的。用户可以随意修改对话框中的数据对象。 "
#. Tag: para
#, no-c-format
msgid "The user clicks \"Save\" after 5 minutes and expects their modifications to be made persistent. The user also expects that they were the only person editing this information and that no conflicting modification has occurred."
msgstr "5 分钟后,用户点击“保存”,期望所做出的修改被持久化;同时他也期望自己是唯一修改这个信息的人,不会出现修改冲突。 "
#. Tag: para
#, no-c-format
msgid "From the point of view of the user, we call this unit of work a long-running <emphasis>conversation or application transaction. There are many ways to implement this in your application."
msgstr "从用户的角度来看,我们把这个操作单元称为长时间运行的<emphasis>对话(conversation),或者应用事务(application transaction)。在你的应用程序中,可以有很多种方法来实现它。"
#. Tag: para
#, no-c-format
msgid "A first naive implementation might keep the <literal>Session and database transaction open during user think time, with locks held in the database to prevent concurrent modification and to guarantee isolation and atomicity. This is an anti-pattern, since lock contention would not allow the application to scale with the number of concurrent users."
msgstr "头一个幼稚的做法是,在用户思考的过程中,保持 <literal>Session 和数据库事务是打开的,保持数据库锁定,以阻止并发修改,从而保证数据库事务隔离级别和原子操作。这种方式当然是一个反模式,因为锁争用会导致应用程序无法扩展并发用户的数目。 "
#. Tag: para
#, no-c-format
msgid "You have to use several database transactions to implement the conversation. In this case, maintaining isolation of business processes becomes the partial responsibility of the application tier. A single conversation usually spans several database transactions. It will be atomic if only one of these database transactions (the last one) stores the updated data. All others simply read data (for example, in a wizard-style dialog spanning several request/response cycles). This is easier to implement than it might sound, especially if you utilize some of Hibernate's features:"
msgstr "很明显,我们必须使用多个数据库事务来实现这个对话。在这个例子中,维护业务处理的 事务隔离变成了应用程序层的部分责任。一个对话通常跨越多个数据库事务。如果仅仅只有一个数据库事务(最后的那个事务)保存更新过的数据,而所有其他事务只是单纯的读取数据(例如在一个跨越多个请求/响应周期的向导风格的对话框中),那么应用程序事务将保证其原子性。这种方式比听起来还要容易实现,特别是当你使用了 Hibernate 的下述特性的时候: "
#. Tag: para
#, no-c-format
msgid "<emphasis>Automatic Versioning: Hibernate can perform automatic optimistic concurrency control for you. It can automatically detect if a concurrent modification occurred during user think time. Check for this at the end of the conversation."
msgstr "<emphasis>自动版本化:Hibernate 能够自动进行乐观并发控制,如果在用户思考的过程中发生并发修改,Hibernate 能够自动检测到。一般我们只在对话结束时才检查。"
#. Tag: para
#, no-c-format
msgid "<emphasis>Detached Objects: if you decide to use the session-per-request pattern, all loaded instances will be in the detached state during user think time. Hibernate allows you to reattach the objects and persist the modifications. The pattern is called session-per-request-with-detached-objects. Automatic versioning is used to isolate concurrent modifications."
msgstr "<emphasis>脱管对象(Detached Objects):如果你决定采用前面已经讨论过的 session-per-request 模式,所有载入的实例在用户思考的过程中都处于与 Session 脱离的状态。Hibernate 允许你把与 Session 脱离的对象重新关联到 Session 上,并且对修改进行持久化,这种模式被称为 session-per-request-with-detached-objects。自动版本化被用来隔离并发修改。"
#. Tag: para
#, no-c-format
msgid "<emphasis>Extended (or Long) Session: the Hibernate Session can be disconnected from the underlying JDBC connection after the database transaction has been committed and reconnected when a new client request occurs. This pattern is known as session-per-conversation and makes even reattachment unnecessary. Automatic versioning is used to isolate concurrent modifications and the Session will not be allowed to be flushed automatically, but explicitly."
msgstr "<emphasis>Extended (or Long) Session:Hibernate 的 Session 可以在数据库事务提交之后和底层的 JDBC 连接断开,当一个新的客户端请求到来的时候,它又重新连接上底层的 JDBC 连接。这种模式被称之为session-per-conversation,这种情况可 能会造成不必要的 Session 和 JDBC 连接的重新关联。自动版本化被用来隔离并发修改,Session 通常不允许自动 flush,而是显性地 flush。 "
#. Tag: para
#, no-c-format
msgid "Both <emphasis>session-per-request-with-detached-objects and session-per-conversation have advantages and disadvantages. These disadvantages are discussed later in this chapter in the context of optimistic concurrency control."
msgstr "<emphasis>session-per-request-with-detached-objects 和 session-per-conversation 各有优缺点,我们在本章后面乐观并发控制那部分再进行讨论。 "
#. Tag: title
#, no-c-format
msgid "Considering object identity"
msgstr "关注对象标识(Considering object identity)"
#. Tag: para
#, no-c-format
msgid "An application can concurrently access the same persistent state in two different <literal>Sessions. However, an instance of a persistent class is never shared between two Session instances. It is for this reason that there are two different notions of identity:"
msgstr "应用程序可能在两个不同的 <literal>Session 中并发访问同一持久化状态,但是,一个持久化类的实例无法在两个 Session 中共享。因此有两种不同的标识语义: "
#. Tag: term
#, no-c-format
msgid "Database Identity"
msgstr "数据库标识"
#. Tag: para
#, no-c-format
msgid "<literal>foo.getId().equals( bar.getId() )"
msgstr "<literal>foo.getId().equals( bar.getId() ) "
#. Tag: term
#, no-c-format
msgid "JVM Identity"
msgstr "JVM 标识"
#. Tag: para
#, no-c-format
msgid "<literal>foo==bar"
msgstr "<literal>foo==bar"
#. Tag: para
#, no-c-format
msgid "For objects attached to a <emphasis>particular Session (i.e., in the scope of a Session), the two notions are equivalent and JVM identity for database identity is guaranteed by Hibernate. While the application might concurrently access the \"same\" (persistent identity) business object in two different sessions, the two instances will actually be \"different\" (JVM identity). Conflicts are resolved using an optimistic approach and automatic versioning at flush/commit time."
msgstr "对于那些关联到 <emphasis>特定 Session(也就是在单个 Session 的范围内)上的对象来说,这两种标识的语义是等价的,与数据库标识对应的 JVM 标识是由 Hibernate 来保证的。不过,当应用程序在两个不同的 session 中并发访问具有同一持久化标识的业务对象实例的时候,这个业务对象的两个实例事实上是不相同的(从 JVM 识别来看)。这种冲突可以通过在同步和提交的时候使用自动版本化和乐观锁定方法来解决。 "
#. Tag: para
#, no-c-format
msgid "This approach leaves Hibernate and the database to worry about concurrency. It also provides the best scalability, since guaranteeing identity in single-threaded units of work means that it does not need expensive locking or other means of synchronization. The application does not need to synchronize on any business object, as long as it maintains a single thread per <literal>Session. Within a Session the application can safely use == to compare objects."
msgstr "这种方式把关于并发的头疼问题留给了 Hibernate 和数据库;由于在单个线程内,操作单元中的对象识别不 需要代价昂贵的锁定或其他意义上的同步,因此它同时可以提供最好的可伸缩性。只要在单个线程只持有一个 <literal>Session,应用程序就不需要同步任何业务对象。在 Session 的范围内,应用程序可以放心的使用 == 进行对象比较。 "
#. Tag: para
#, no-c-format
msgid "However, an application that uses <literal>== outside of a Session might produce unexpected results. This might occur even in some unexpected places. For example, if you put two detached instances into the same Set, both might have the same database identity (i.e., they represent the same row). JVM identity, however, is by definition not guaranteed for instances in a detached state. The developer has to override the equals() and hashCode() methods in persistent classes and implement their own notion of object equality. There is one caveat: never use the database identifier to implement equality. Use a business key that is a combination of unique, usually immutable, attributes. The database identifier will change if a transient object is made persistent. If the transient instance (usually together with detached instances) is held in a Set, changing the hashcode breaks the contract of the Set. Attributes for business keys do not have to be as stable as database primary keys; you only have to guarantee stability as long as the objects are in the same Set. See the Hibernate website for a more thorough discussion of this issue. Please note that this is not a Hibernate issue, but simply how Java object identity and equality has to be implemented."
msgstr "不过,应用程序在 <literal>Session 的外面使用 == 进行对象比较可能会 导致无法预期的结果。在一些无法预料的场合,例如,如果你把两个脱管对象实例放进同一个 Set 的时候,就可能发生。这两个对象实例可能有同一个数据库标识(也就是说, 他们代表了表的同一行数据),从 JVM 标识的定义上来说,对脱管的对象而言,Hibernate 无法保证他们 的的 JVM 标识一致。开发人员必须覆盖持久化类的 equals() 方法和 hashCode() 方法,从而实现自定义的对象相等语义。警告:不要使用数据库标识来实现对象相等,应该使用业务键值,由唯一的,通常不变的属性组成。当一个瞬时对象被持久化的时候,它的数据库标识会发生改变。如果一个瞬时对象(通常也包括脱管对象实例)被放入一个 Set,改变它的 hashcode 会导致与这个 Set 的关系中断。虽 然业务键值的属性不象数据库主键那样稳定不变,但是你只需要保证在同一个 Set 中的对象属性的稳定性就足够了。请到 Hibernate 网站去寻求这个问题更多的详细的讨论。请注意,这不是一个有关 Hibernate 的问题,而仅仅是一个关于 Java 对象标识和判等行为如何实现的问题。 "
#. Tag: title
#, no-c-format
msgid "Common issues"
msgstr "常见问题"
#. Tag: para
#, no-c-format
msgid "Do not use the anti-patterns <emphasis>session-per-user-session or session-per-application (there are, however, rare exceptions to this rule). Some of the following issues might also arise within the recommended patterns, so ensure that you understand the implications before making a design decision:"
msgstr "决不要使用反模式 <emphasis>session-per-user-session 或者 session-per-application(当然,这个规定几乎没有例外)。请注意,下述一些问题可能也会出现在我们推荐的模式中,在你作出某个设计决定之前,请务必理解该模式的应用前提。 "
#. Tag: para
#, no-c-format
msgid "A <literal>Session is not thread-safe. Things that work concurrently, like HTTP requests, session beans, or Swing workers, will cause race conditions if a Session instance is shared. If you keep your Hibernate Session in your HttpSession (this is discussed later in the chapter), you should consider synchronizing access to your Http session. Otherwise, a user that clicks reload fast enough can use the same Session in two concurrently running threads."
msgstr "<literal>Session 对象是非线程安全的。如果一个 Session 实例允许共享的话,那些支持并发运行的东东,例如 HTTP request,session beans 或者是 Swing workers,将会导致出现资源争用(race condition)。如果在 HttpSession 中有 Hibernate 的 Session 的话(稍后讨论),你应该考虑同步访问你的 Http session。 否则,只要用户足够快的点击浏览器的“刷新”,就会导致两个并发运行线程使用同一个 Session。 "
#. Tag: para
#, no-c-format
msgid "An exception thrown by Hibernate means you have to rollback your database transaction and close the <literal>Session immediately (this is discussed in more detail later in the chapter). If your Session is bound to the application, you have to stop the application. Rolling back the database transaction does not put your business objects back into the state they were at the start of the transaction. This means that the database state and the business objects will be out of sync. Usually this is not a problem, because exceptions are not recoverable and you will have to start over after rollback anyway."
msgstr "一个由 Hibernate 抛出的异常意味着你必须立即回滚数据库事务,并立即关闭 <literal>Session(稍后会展开讨论)。如果你的 Session 绑定到一个应用程序上,你必须停止该应用程序。回滚数据库事务并不会把你的业务对象退回到事务启动时候的状态。这意味着数据库状态和业务对象状态不同步。通常情况下,这不是什么问题,因为异常是不可恢复的,你必须在回滚之后重新开始执行。 "
#. Tag: para
#, no-c-format
msgid "The <literal>Session caches every object that is in a persistent state (watched and checked for dirty state by Hibernate). If you keep it open for a long time or simply load too much data, it will grow endlessly until you get an OutOfMemoryException. One solution is to call clear() and evict() to manage the Session cache, but you should consider a Stored Procedure if you need mass data operations. Some solutions are shown in . Keeping a Session open for the duration of a user session also means a higher probability of stale data."
msgstr "<literal>Session 缓存了处于持久化状态的每个对象(Hibernate 会监视和检查脏数据)。 这意味着,如果你让 Session 打开很长一段时间,或是仅仅载入了过多的数据, Session 占用的内存会一直增长,直到抛出 OutOfMemoryException 异常。这个 问题的一个解决方法是调用 clear() 和 evict() 来管理 Session 的缓存,但是如果你需要大批量数据操作的话,最好考虑使用存储过程。在中有一些解决方案。在用户会话期间一直保持 Session 打开也意味着出现脏数据的可能性很高。 "
#. Tag: title
#, no-c-format
msgid "Database transaction demarcation"
msgstr "数据库事务声明"
#. Tag: para
#, no-c-format
msgid "Database, or system, transaction boundaries are always necessary. No communication with the database can occur outside of a database transaction (this seems to confuse many developers who are used to the auto-commit mode). Always use clear transaction boundaries, even for read-only operations. Depending on your isolation level and database capabilities this might not be required, but there is no downside if you always demarcate transactions explicitly. Certainly, a single database transaction is going to perform better than many small transactions, even for reading data."
msgstr "数据库(或者系统)事务的声明总是必须的。在数据库事务之外,就无法和数据库通讯(这可能会让那些习惯于自动提交事务模式的开发人员感到迷惑)。永远使用清晰的事务声明,即使只读操作也是如此。进行 显式的事务声明并不总是需要的,这取决于你的事务隔离级别和数据库的能力,但不管怎么说,声明事务总归有益无害。当然,一个单独的数据库事务总是比很多琐碎的事务性能更好,即时对读数据而言也是一样。 "
#. Tag: para
#, no-c-format
msgid "A Hibernate application can run in non-managed (i.e., standalone, simple Web- or Swing applications) and managed J2EE environments. In a non-managed environment, Hibernate is usually responsible for its own database connection pool. The application developer has to manually set transaction boundaries (begin, commit, or rollback database transactions) themselves. A managed environment usually provides container-managed transactions (CMT), with the transaction assembly defined declaratively (in deployment descriptors of EJB session beans, for example). Programmatic transaction demarcation is then no longer necessary."
msgstr "一个 Hibernate 应用程序可以运行在非托管环境中(也就是独立运行的应用程序,简单 Web 应用程序,或者Swing图形桌面应用程序),也可以运行在托管的 J2EE 环境中。在一个非托管环境中,Hibernate 通常自己负责管理数据库连接池。应用程序开发人员必须手工设置事务声明,换句话说,就是手工启 动,提交,或者回滚数据库事务。一个托管的环境通常提供了容器管理事务(CMT),例如事务装配通过可声明的方式定义在 EJB session beans 的部署描述符中。可编程式事务声明不再需要,即使是 <literal>Session 的同步也可以自动完成。 "
#. Tag: para
#, no-c-format
msgid "However, it is often desirable to keep your persistence layer portable between non-managed resource-local environments, and systems that can rely on JTA but use BMT instead of CMT. In both cases use programmatic transaction demarcation. Hibernate offers a wrapper API called <literal>Transaction that translates into the native transaction system of your deployment environment. This API is actually optional, but we strongly encourage its use unless you are in a CMT session bean."
msgstr "让持久层具备可移植性是人们的理想,这种移植发生在非托管的本地资源环境,与依赖 JTA 但是使用 BMT 而非 CMT 的系统之间。在两种情况下你都可以使用编程式的事务管理。Hibernate 提供了一套称为 <literal>Transaction 的封装 API, 用来把你的部署环境中的本地事务管理系统转换到 Hibernate 事务上。这个 API 是可选的,但是我们强烈推荐你使用,除非你用 CMT session bean。 "
#. Tag: para
#, no-c-format
msgid "Ending a <literal>Session usually involves four distinct phases:"
msgstr "通常情况下,结束 <literal>Session 包含了四个不同的阶段: "
#. Tag: para
#, no-c-format
msgid "flush the session"
msgstr "同步 session(flush,刷出到磁盘)"
#. Tag: para
#, no-c-format
msgid "commit the transaction"
msgstr "提交事务"
#. Tag: para
#, no-c-format
msgid "close the session"
msgstr "关闭 session"
#. Tag: para
#, no-c-format
msgid "handle exceptions"
msgstr "处理异常"
#. Tag: para
#, no-c-format
msgid "We discussed Flushing the session earlier, so we will now have a closer look at transaction demarcation and exception handling in both managed and non-managed environments."
msgstr "session 的同步(flush,刷出)前面已经讨论过了,我们现在进一步考察在托管和非托管环境下的事务声明和异常处理。 "
#. Tag: title
#, no-c-format
msgid "Non-managed environment"
msgstr "非托管环境"
#. Tag: para
#, no-c-format
msgid "If a Hibernate persistence layer runs in a non-managed environment, database connections are usually handled by simple (i.e., non-DataSource) connection pools from which Hibernate obtains connections as needed. The session/transaction handling idiom looks like this:"
msgstr "如果 Hibernat 持久层运行在一个非托管环境中,数据库连接通常由 Hibernate 的简单(即非 DataSource)连接池机制 来处理。session/transaction 处理方式如下所示: "
#. Tag: para
#, no-c-format
msgid "You do not have to <literal>flush() the Session explicitly: the call to commit() automatically triggers the synchronization depending on the FlushMode for the session. A call to close() marks the end of a session. The main implication of close() is that the JDBC connection will be relinquished by the session. This Java code is portable and runs in both non-managed and JTA environments."
msgstr "你不需要显式 <literal>flush() Session — 对 commit() 的调用会自动触发 session 的同步(取决于 session 的 )。调用 close() 标志 session 的结束。close() 方法重要的暗示是,session 释放了 JDBC 连接。这段 Java 代码在非托管环境下和 JTA 环境下都可以运行。 "
#. Tag: para
#, no-c-format
msgid "As outlined earlier, a much more flexible solution is Hibernate's built-in \"current session\" context management:"
msgstr "更加灵活的方案是 Hibernate 内置的 \"current session\" 上下文管理,前文已经讲过: "
#. Tag: para
#, no-c-format
msgid "You will not see these code snippets in a regular application; fatal (system) exceptions should always be caught at the \"top\". In other words, the code that executes Hibernate calls in the persistence layer, and the code that handles <literal>RuntimeException (and usually can only clean up and exit), are in different layers. The current context management by Hibernate can significantly simplify this design by accessing a SessionFactory. Exception handling is discussed later in this chapter."
msgstr "你很可能从未在一个通常的应用程序的业务代码中见过这样的代码片断:致命的(系统)异常应该总是 在应用程序“顶层”被捕获。换句话说,执行 Hibernate 调用的代码(在持久层)和处理 <literal>RuntimeException 异常的代码(通常只能清理和退出应用程序)应该在不同 的应用程序逻辑层。Hibernate 的当前上下文管理可以极大地简化这一设计,你所有的一切就是 SessionFactory。异常处理将在本章稍后进行讨论。 "
#. Tag: para
#, no-c-format
msgid "You should select <literal>org.hibernate.transaction.JDBCTransactionFactory, which is the default, and for the second example select \"thread\" as your hibernate.current_session_context_class."
msgstr "请注意,你应该选择 <literal>org.hibernate.transaction.JDBCTransactionFactory (这是默认选项),对第二个例子来说,hibernate.current_session_context_class应该是 \"thread\"。"
#. Tag: title
#, no-c-format
msgid "Using JTA"
msgstr "使用 JTA"
#. Tag: para
#, no-c-format
msgid "If your persistence layer runs in an application server (for example, behind EJB session beans), every datasource connection obtained by Hibernate will automatically be part of the global JTA transaction. You can also install a standalone JTA implementation and use it without EJB. Hibernate offers two strategies for JTA integration."
msgstr "如果你的持久层运行在一个应用服务器中(例如,在 EJB session beans 的后面),Hibernate 获取的每个数据源连接将自动成为全局 JTA 事务的一部分。你可以安装一个独立的 JTA 实现,使用它而不使用 EJB。Hibernate 提供了两种策略进行 JTA 集成。 "
#. Tag: para
#, no-c-format
msgid "If you use bean-managed transactions (BMT), Hibernate will tell the application server to start and end a BMT transaction if you use the <literal>Transaction API. The transaction management code is identical to the non-managed environment."
msgstr "如果你使用 bean 管理事务(BMT),可以通过使用 Hibernate 的 <literal>Transaction API 来告诉应用服务器启动和结束 BMT 事务。因此,事务管理代码和在非托管环境下是一样的。 "
#. Tag: para
#, no-c-format
msgid "If you want to use a transaction-bound <literal>Session, that is, the getCurrentSession() functionality for easy context propagation, use the JTA UserTransaction API directly:"
msgstr "如果你希望使用与事务绑定的 <literal>Session,也就是使用 getCurrentSession() 来简化上下文管理,你将不得不直接使用 JTA UserTransaction API。 "
#. Tag: para
#, no-c-format
msgid "With CMT, transaction demarcation is completed in session bean deployment descriptors, not programmatically. The code is reduced to:"
msgstr "在 CMT 方式下,事务声明是在 session bean 的部署描述符中,而不需要编程。因此,代码被简化为:"
#. Tag: para
#, no-c-format
msgid "In a CMT/EJB, even rollback happens automatically. An unhandled <literal>RuntimeException thrown by a session bean method tells the container to set the global transaction to rollback. You do not need to use the Hibernate Transaction API at all with BMT or CMT, and you get automatic propagation of the \"current\" Session bound to the transaction."
msgstr "在 CMT/EJB 中甚至会自动 rollback,因为假若有未捕获的 <literal>RuntimeException 从 session bean 方法中抛出,这就会通知容器把全局事务回滚。这就意味着,在 BMT 或者 CMT 中,你根本就不需要使用 Hibernate Transaction API,你自动得到了绑定到事务的“当前” Session。"
#. Tag: para
#, no-c-format
msgid "When configuring Hibernate's transaction factory, choose <literal>org.hibernate.transaction.JTATransactionFactory if you use JTA directly (BMT), and org.hibernate.transaction.CMTTransactionFactory in a CMT session bean. Remember to also set hibernate.transaction.manager_lookup_class. Ensure that your hibernate.current_session_context_class is either unset (backwards compatibility), or is set to \"jta\"."
msgstr "注意,当你配置 Hibernate 的 transaction factory 的时候,在直接使用 JTA 的时候(BMT),你应该选择 <literal>org.hibernate.transaction.JTATransactionFactory,在 CMT session bean 中选择 org.hibernate.transaction.CMTTransactionFactory。记得也要设置 hibernate.transaction.manager_lookup_class。还有,确认你的 hibernate.current_session_context_class 未设置(为了向下兼容),或者设置为 \"jta\"。 "
#. Tag: para
#, no-c-format
msgid "The <literal>getCurrentSession() operation has one downside in a JTA environment. There is one caveat to the use of after_statement connection release mode, which is then used by default. Due to a limitation of the JTA spec, it is not possible for Hibernate to automatically clean up any unclosed ScrollableResults or Iterator instances returned by scroll() or iterate(). You must release the underlying database cursor by calling ScrollableResults.close() or Hibernate.close(Iterator) explicitly from a finally block. Most applications can easily avoid using scroll() or iterate() from the JTA or CMT code.)"
msgstr "<literal>getCurrentSession()在 JTA 环境中有一个弊端。对 after_statement 连接释放方式有一个警告,这是被默认使用的。因为 JTA 规范的一个很愚蠢的限制,Hibernate 不可能自动清理任何未关闭的 ScrollableResults 或者Iterator,它们是由 scroll() 或 iterate() 产生的。你 must 通过在 finally 块中,显式调用 ScrollableResults.close() 或者 Hibernate.close(Iterator) 方法来释放底层数据库游标。(当然,大部分程序完全可以很容易的避免在 JTA 或 CMT 代码中出现 scroll() 或 iterate()。) "
#. Tag: title
#, no-c-format
msgid "Exception handling"
msgstr "异常处理"
#. Tag: para
#, no-c-format
msgid "If the <literal>Session throws an exception, including any SQLException, immediately rollback the database transaction, call Session.close() and discard the Session instance. Certain methods of Session will not leave the session in a consistent state. No exception thrown by Hibernate can be treated as recoverable. Ensure that the Session will be closed by calling close() in a finally block."
msgstr "如果 <literal>Session 抛出异常(包括任何 SQLException),你应该立即回滚数据库事务,调用 Session.close() ,丢弃该 Session 实例。Session 的某些方法可能会导致 session 处于不一致的状态。所有由 Hibernate 抛出的异常都视为不可以恢复的。确保在 finally 代码块中调用 close() 方法,以关闭掉 Session。"
#. Tag: para
#, no-c-format
msgid "The <literal>HibernateException, which wraps most of the errors that can occur in a Hibernate persistence layer, is an unchecked exception. It was not in older versions of Hibernate. In our opinion, we should not force the application developer to catch an unrecoverable exception at a low layer. In most systems, unchecked and fatal exceptions are handled in one of the first frames of the method call stack (i.e., in higher layers) and either an error message is presented to the application user or some other appropriate action is taken. Note that Hibernate might also throw other unchecked exceptions that are not a HibernateException. These are not recoverable and appropriate action should be taken."
msgstr "<literal>HibernateException 是一个非检查期异常(这不同于 Hibernate 老的版本),它封装了 Hibernate 持久层可能出现的大多数错误。我们的观点是,不应该强迫应用程序开发人员 在底层捕获无法恢复的异常。在大多数软件系统中,非检查期异常和致命异常都是在相应方法调用 的堆栈的顶层被处理的(也就是说,在软件上面的逻辑层),并且提供一个错误信息给应用软件的用户 (或者采取其他某些相应的操作)。请注意,Hibernate 也有可能抛出其他并不属于 HibernateException 的非检查期异常。这些异常同样也是无法恢复的,应该 采取某些相应的操作去处理。"
#. Tag: para
#, no-c-format
msgid "Hibernate wraps <literal>SQLExceptions thrown while interacting with the database in a JDBCException. In fact, Hibernate will attempt to convert the exception into a more meaningful subclass of JDBCException. The underlying SQLException is always available via JDBCException.getCause(). Hibernate converts the SQLException into an appropriate JDBCException subclass using the SQLExceptionConverter attached to the SessionFactory. By default, the SQLExceptionConverter is defined by the configured dialect. However, it is also possible to plug in a custom implementation. See the javadocs for the SQLExceptionConverterFactory class for details. The standard JDBCException subtypes are:"
msgstr "在和数据库进行交互时,Hibernate 把捕获的 <literal>SQLException 封装为 Hibernate 的 JDBCException。事实上,Hibernate 尝试把异常转换为更有实际含义的 JDBCException 异常的子类。底层的 SQLException 可以通过 JDBCException.getCause() 来得到。Hibernate 通过使用关联到 SessionFactory 上的 SQLExceptionConverter 来把 SQLException 转换为一个对应的 JDBCException 异常的子类。默认情况下,SQLExceptionConverter 可以通过配置 dialect 选项指定;此外,也可以使用用户自定义的实现类(参考 javadocs SQLExceptionConverterFactory 类来了解详情)。标准的 JDBCException 子类型是: "
#. Tag: para
#, no-c-format
msgid "<literal>JDBCConnectionException: indicates an error with the underlying JDBC communication."
msgstr "<literal>JDBCConnectionException:指明底层的 JDBC 通讯出现错误。"
#. Tag: para
#, no-c-format
msgid "<literal>SQLGrammarException: indicates a grammar or syntax problem with the issued SQL."
msgstr "<literal>SQLGrammarException:指明发送的 SQL 语句的语法或者格式错误。"
#. Tag: para
#, no-c-format
msgid "<literal>ConstraintViolationException: indicates some form of integrity constraint violation."
msgstr "<literal>ConstraintViolationException:指明某种类型的约束违例错误"
#. Tag: para
#, no-c-format
msgid "<literal>LockAcquisitionException: indicates an error acquiring a lock level necessary to perform the requested operation."
msgstr "<literal>LockAcquisitionException:指明了在执行请求操作时,获取所需的锁级别时出现的错误。"
#. Tag: para
#, no-c-format
msgid "<literal>GenericJDBCException: a generic exception which did not fall into any of the other categories."
msgstr "<literal>GenericJDBCException:不属于任何其他种类的原生异常。"
#. Tag: title
#, no-c-format
msgid "Transaction timeout"
msgstr "事务超时"
#. Tag: para
#, no-c-format
msgid "An important feature provided by a managed environment like EJB, that is never provided for non-managed code, is transaction timeout. Transaction timeouts ensure that no misbehaving transaction can indefinitely tie up resources while returning no response to the user. Outside a managed (JTA) environment, Hibernate cannot fully provide this functionality. However, Hibernate can at least control data access operations, ensuring that database level deadlocks and queries with huge result sets are limited by a defined timeout. In a managed environment, Hibernate can delegate transaction timeout to JTA. This functionality is abstracted by the Hibernate <literal>Transaction object."
msgstr "EJB 这样的托管环境有一项极为重要的特性,而它从未在非托管环境中提供过,那就是事务超时。在出现错误的事务行为的时候,超时可以确保不会无限挂起资源、对用户没有交代。在托管(JTA)环境之外,Hibernate 无法完全提供这一功能。但是,Hiberante 至少可以控制数据访问,确保数据库级别的死锁,和返回巨大结果集的查询被限定在一个规定的时间内。在托管环境中,Hibernate 会把事务超时转交给 JTA。这一功能通过 Hibernate <literal>Transaction 对象进行抽象。 "
#. Tag: para
#, no-c-format
msgid "<literal>setTimeout() cannot be called in a CMT bean, where transaction timeouts must be defined declaratively."
msgstr "注意 <literal>setTimeout() 不应该在 CMT bean 中调用,此时事务超时值应该是被声明式定义的。 "
#. Tag: title
#, no-c-format
msgid "Optimistic concurrency control"
msgstr "乐观并发控制(Optimistic concurrency control)"
#. Tag: para
#, no-c-format
msgid "The only approach that is consistent with high concurrency and high scalability, is optimistic concurrency control with versioning. Version checking uses version numbers, or timestamps, to detect conflicting updates and to prevent lost updates. Hibernate provides three possible approaches to writing application code that uses optimistic concurrency. The use cases we discuss are in the context of long conversations, but version checking also has the benefit of preventing lost updates in single database transactions."
msgstr "唯一能够同时保持高并发和高可伸缩性的方法就是使用带版本化的乐观并发控制。版本检查使用版本号、 或者时间戳来检测更新冲突(并且防止更新丢失)。Hibernate 为使用乐观并发控制的代码提供了三种可 能的方法,应用程序在编写这些代码时,可以采用它们。我们已经在前面应用程序对话那部分展示了 乐观并发控制的应用场景,此外,在单个数据库事务范围内,版本检查也提供了防止更新丢失的好处。 "
#. Tag: title
#, no-c-format
msgid "Application version checking"
msgstr "应用程序级别的版本检查(Application version checking)"
#. Tag: para
#, no-c-format
msgid "In an implementation without much help from Hibernate, each interaction with the database occurs in a new <literal>Session and the developer is responsible for reloading all persistent instances from the database before manipulating them. The application is forced to carry out its own version checking to ensure conversation transaction isolation. This approach is the least efficient in terms of database access. It is the approach most similar to entity EJBs."
msgstr "未能充分利用 Hibernate 功能的实现代码中,每次和数据库交互都需要一个新的 <literal>Session,而且开发人员必须在显示数据之前从数据库中重新载入所有的持久化对象实例。这种方式迫使应用程序自己实现版本检查来确保对话事务的隔离,从数据访问的角度来说是最低效的。这种使用方式和 entity EJB 最相似。 "
#. Tag: para
#, no-c-format
msgid "The <literal>version property is mapped using <version>, and Hibernate will automatically increment it during flush if the entity is dirty."
msgstr "<literal>version 属性使用 <version> 来映射,如果对象是脏数据,在同步的时候,Hibernate 会自动增加版本号。"
#. Tag: para
#, no-c-format
msgid "If you are operating in a low-data-concurrency environment, and do not require version checking, you can use this approach and skip the version check. In this case, <emphasis>last commit wins is the default strategy for long conversations. Be aware that this might confuse the users of the application, as they might experience lost updates without error messages or a chance to merge conflicting changes."
msgstr "当然,如果你的应用是在一个低数据并发环境下,并不需要版本检查的话,你照样可以使用这种方式,只不过跳过版本检查就是了。在这种情况下,<emphasis>最晚提交生效 (last commit wins)就是你的长对话的默认处理策略。请记住这种策略可能会让应用软件的用户感到困惑,因为他们有可能会碰上更新丢失掉却没有出错信息,或者需要合并更改冲突的情况。 "
#. Tag: para
#, no-c-format
msgid "Manual version checking is only feasible in trivial circumstances and not practical for most applications. Often not only single instances, but complete graphs of modified objects, have to be checked. Hibernate offers automatic version checking with either an extended <literal>Session or detached instances as the design paradigm."
msgstr "很明显,手工进行版本检查只适合于某些软件规模非常小的应用场景,对于大多数软件应用场景来说并不现实。通常情况下,不仅是单个对象实例需要进行版本检查,整个被修改过的关联对象图也都需要进行版本检查。作为标准设计范例,Hibernate 使用扩展周期的 <literal>Session 的方式,或者脱管对象实例的方式来提供自动版本检查。 "
#. Tag: title
#, no-c-format
msgid "Extended session and automatic versioning"
msgstr "扩展周期的 session 和自动版本化"
#. Tag: para
#, no-c-format
msgid "A single <literal>Session instance and its persistent instances that are used for the whole conversation are known as session-per-conversation. Hibernate checks instance versions at flush time, throwing an exception if concurrent modification is detected. It is up to the developer to catch and handle this exception. Common options are the opportunity for the user to merge changes or to restart the business conversation with non-stale data."
msgstr "单个 <literal>Session 实例和它所关联的所有持久化对象实例都被用于整个对话,这被称为 session-per-conversation。Hibernate 在同步的时候进行对象实例的版本检查,如果检测到并发修改则抛出异常。由开发人员来决定是否需要捕获和处理这个异常(通常的抉择是给用户 提供一个合并更改,或者在无脏数据情况下重新进行业务对话的机会)。 "
#. Tag: para
#, no-c-format
msgid "The <literal>Session is disconnected from any underlying JDBC connection when waiting for user interaction. This approach is the most efficient in terms of database access. The application does not version check or reattach detached instances, nor does it have to reload instances in every database transaction."
msgstr "在等待用户交互的时候, <literal>Session 断开底层的 JDBC 连接。这种方式以数据库访问的角度来说是最高效的方式。应用程序不需要关心版本检查或脱管对象实例的重新关联,在每个数据库事务中,应用程序也不需要载入读取对象实例。 "
#. Tag: para
#, no-c-format
msgid "The <literal>foo object knows which Session it was loaded in. Beginning a new database transaction on an old session obtains a new connection and resumes the session. Committing a database transaction disconnects a session from the JDBC connection and returns the connection to the pool. After reconnection, to force a version check on data you are not updating, you can call Session.lock() with LockMode.READ on any objects that might have been updated by another transaction. You do not need to lock any data that you are updating. Usually you would set FlushMode.MANUAL on an extended Session, so that only the last database transaction cycle is allowed to actually persist all modifications made in this conversation. Only this last database transaction will include the flush() operation, and then close() the session to end the conversation."
msgstr "<literal>foo 对象知道它是在哪个 Session 中被装入的。在一个旧 session 中开启一个新的数据库事务,会导致 session 获取一个新的连接,并恢复 session 的功能。将数据库事务提交,使得 session 从 JDBC 连接断开,并将此连接交还给连接池。在重新连接之后,要强制对你没有更新的数据进行一次版本检查,你可以对所有可能被其他事务修改过的对象,使用参数 LockMode.READ 来调用 Session.lock()。你不用 lock 任何你正在更新的数据。一般你会在扩展的 Session 上设置 FlushMode.NEVER,因此只有最后一个数据库事务循环才会真正的把整个对话中发生的修改发送到数据库。因此,只有这最后一次数据库事务才会包含 flush() 操作,然后在整个对话结束后,还要 close() 这个 session。 "
#. Tag: para
#, no-c-format
msgid "This pattern is problematic if the <literal>Session is too big to be stored during user think time (for example, an HttpSession should be kept as small as possible). As the Session is also the first-level cache and contains all loaded objects, we can probably use this strategy only for a few request/response cycles. Use a Session only for a single conversation as it will soon have stale data."
msgstr "如果在用户思考的过程中,<literal>Session 因为太大了而不能保存,那么这种模式是有问题的。举例来说,一个 HttpSession 应该尽可能的小。由于 Session 是一级缓存,并且保持了所有被载入过的对象,因此我们只应该在那些少量的 request/response 情况下使用这种策略。你应该只把一个 Session 用于单个对话,因为它很快就会出现脏数据。 "
#. Tag: title
#, no-c-format
msgid "Note"
msgstr "注意"
#. Tag: para
#, no-c-format
msgid "Earlier versions of Hibernate required explicit disconnection and reconnection of a <literal>Session. These methods are deprecated, as beginning and ending a transaction has the same effect."
msgstr "注意,早期的 Hibernate 版本需要明确的对 <literal>Session 进行 disconnect 和 reconnect。这些方法现在已经过时了,打开事务和关闭事务会起到同样的效果。"
#. Tag: para
#, no-c-format
msgid "Keep the disconnected <literal>Session close to the persistence layer. Use an EJB stateful session bean to hold the Session in a three-tier environment. Do not transfer it to the web layer, or even serialize it to a separate tier, to store it in the HttpSession."
msgstr "此外,也请注意,你应该让与数据库连接断开的 <literal>Session 对持久层保持关闭状态。换句话说,在三层环境中,使用有状态的 EJB session bean 来持 有Session, 而不要把它传递到 web 层(甚至把它序列化到一个单独的层),保存在 HttpSession 中。 "
#. Tag: para
#, no-c-format
msgid "The extended session pattern, or <emphasis>session-per-conversation, is more difficult to implement with automatic current session context management. You need to supply your own implementation of the CurrentSessionContext for this. See the Hibernate Wiki for examples."
msgstr "扩展 session 模式,或者被称为<emphasis>每次对话一个session(session-per-conversation),自动管理当前 session 上下文联用的时候会更困难。你需要提供你自己的 CurrentSessionContext 实现。请参阅 Hibernate Wiki 以获得示例。 "
#. Tag: title
#, no-c-format
msgid "Detached objects and automatic versioning"
msgstr "脱管对象(deatched object)和自动版本化"
#. Tag: para
#, no-c-format
msgid "Each interaction with the persistent store occurs in a new <literal>Session. However, the same persistent instances are reused for each interaction with the database. The application manipulates the state of detached instances originally loaded in another Session and then reattaches them using Session.update(), Session.saveOrUpdate(), or Session.merge()."
msgstr "这种方式下,与持久化存储的每次交互都发生在一个新的 <literal>Session 中。然而,同一持久化对象实例可以在多次与数据库的交互中重用。应用程序操纵脱管对象实例 的状态,这个脱管对象实例最初是在另一个 Session 中载入的,然后调用 Session.update(),Session.saveOrUpdate(),或者 Session.merge() 来重新关联该对象实例。"
#. Tag: para
#, no-c-format
msgid "Again, Hibernate will check instance versions during flush, throwing an exception if conflicting updates occurred."
msgstr "Hibernate 会再一次在同步的时候检查对象实例的版本,如果发生更新冲突,就抛出异常。 "
#. Tag: para
#, no-c-format
msgid "You can also call <literal>lock() instead of update(), and use LockMode.READ (performing a version check and bypassing all caches) if you are sure that the object has not been modified."
msgstr "如果你确信对象没有被修改过,你也可以调用 <literal>lock() 来设置 LockMode.READ(绕过所有的缓存,执行版本检查),从而取代 update() 操作。 "
#. Tag: title
#, no-c-format
msgid "Customizing automatic versioning"
msgstr "定制自动版本化行为"
#. Tag: para
#, no-c-format
msgid "You can disable Hibernate's automatic version increment for particular properties and collections by setting the <literal>optimistic-lock mapping attribute to false. Hibernate will then no longer increment versions if the property is dirty."
msgstr "对于特定的属性和集合,通过为它们设置映射属性 <literal>optimistic-lock 的值为 false,来禁止 Hibernate 的版本自动增加。这样的话,如果该属性脏数据,Hibernate 将不再增加版本号。 "
#. Tag: para
#, no-c-format
msgid "Legacy database schemas are often static and cannot be modified. Or, other applications might access the same database and will not know how to handle version numbers or even timestamps. In both cases, versioning cannot rely on a particular column in a table. To force a version check with a comparison of the state of all fields in a row but without a version or timestamp property mapping, turn on <literal>optimistic-lock=\"all\" in the <class> mapping. This conceptually only works if Hibernate can compare the old and the new state (i.e., if you use a single long Session and not session-per-request-with-detached-objects)."
msgstr "遗留系统的数据库 Schema 通常是静态的,不可修改的。或者,其他应用程序也可能访问同一数据库,根本无法得知如何处理版本号,甚至时间戳。在以上的所有场景中,实现版本化不能依靠数据库表的某个特定列。在 <literal><class> 的映射中设置 optimistic-lock=\"all\" 可以在没有版本或者时间戳属性映射的情况下实现版本检查,此时 Hibernate 将比较一行记录的每个字段的状态。请注意,只有当 Hibernate 能够比较新旧状态的情况下,这种方式才能生效,也就是说,你必须使用单个长生命周期 Session 模式,而不能使用 session-per-request-with-detached-objects 模式。 "
#. Tag: para
#, no-c-format
msgid "Concurrent modification can be permitted in instances where the changes that have been made do not overlap. If you set <literal>optimistic-lock=\"dirty\" when mapping the <class>, Hibernate will only compare dirty fields during flush."
msgstr "有些情况下,只要更改不发生交错,并发修改也是允许的。当你在 <literal><class> 的映射中设置 optimistic-lock=\"dirty\",Hibernate 在同步的时候将只比较有脏数据的字段。 "
#. Tag: para
#, no-c-format
msgid "In both cases, with dedicated version/timestamp columns or with a full/dirty field comparison, Hibernate uses a single <literal>UPDATE statement, with an appropriate WHERE clause, per entity to execute the version check and update the information. If you use transitive persistence to cascade reattachment to associated entities, Hibernate may execute unnecessary updates. This is usually not a problem, but on update triggers in the database might be executed even when no changes have been made to detached instances. You can customize this behavior by setting select-before-update=\"true\" in the <class> mapping, forcing Hibernate to SELECT the instance to ensure that changes did occur before updating the row."
msgstr "在以上所有场景中,不管是专门设置一个版本/时间戳列,还是进行全部字段/脏数据字段比较,Hibernate 都会针对每个实体对象发送一条 <literal>UPDATE(带有相应的 WHERE 语句 )的 SQL 语句来执行版本检查和数据更新。如果你对关联实体 设置级联关系使用传播性持久化(transitive persistence),那么 Hibernate 可能会执行不必 要的update语句。这通常不是个问题,但是数据库里面对 on update 点火 的触发器可能在脱管对象没有任何更改的情况下被触发。因此,你可以在 <class> 的映射中,通过设置select-before-update=\"true\" 来定制这一行为,强制 Hibernate SELECT 这个对象实例,从而保证,在更新记录之前,对象的确是被修改过。 "
#. Tag: title
#, no-c-format
msgid "Pessimistic locking"
msgstr "悲观锁定(Pessimistic Locking) "
#. Tag: para
#, no-c-format
msgid "It is not intended that users spend much time worrying about locking strategies. It is usually enough to specify an isolation level for the JDBC connections and then simply let the database do all the work. However, advanced users may wish to obtain exclusive pessimistic locks or re-obtain locks at the start of a new transaction."
msgstr "用户其实并不需要花很多精力去担心锁定策略的问题。通常情况下,只要为 JDBC 连接指定一下隔离级别,然后让数据库去搞定一切就够了。然而,高级用户有时候希望进行一个排它的悲观锁定,或者在一个新的事务启动的时候,重新进行锁定。 "
#. Tag: para
#, no-c-format
msgid "Hibernate will always use the locking mechanism of the database; it never lock objects in memory."
msgstr "Hibernate 总是使用数据库的锁定机制,从不在内存中锁定对象。"
#. Tag: para
#, no-c-format
msgid "The <literal>LockMode class defines the different lock levels that can be acquired by Hibernate. A lock is obtained by the following mechanisms:"
msgstr "类 <literal>LockMode 定义了 Hibernate 所需的不同的锁定级别。一个锁定可以通过以下的机制来设置:"
#. Tag: para
#, no-c-format
msgid "<literal>LockMode.WRITE is acquired automatically when Hibernate updates or inserts a row."
msgstr "当 Hibernate 更新或者插入一行记录的时候,锁定级别自动设置为 <literal>LockMode.WRITE。"
#. Tag: para
#, no-c-format
msgid "<literal>LockMode.UPGRADE can be acquired upon explicit user request using SELECT ... FOR UPDATE on databases which support that syntax."
msgstr "当用户显式的使用数据库支持的 SQL 格式 <literal>SELECT ... FOR UPDATE 发送 SQL 的时候,锁定级别设置为 LockMode.UPGRADE。 "
#. Tag: para
#, no-c-format
msgid "<literal>LockMode.UPGRADE_NOWAIT can be acquired upon explicit user request using a SELECT ... FOR UPDATE NOWAIT under Oracle."
msgstr "当用户显式的使用 Oracle 数据库的 SQL 语句 <literal>SELECT ... FOR UPDATE NOWAIT 的时候,锁定级别设置 LockMode.UPGRADE_NOWAIT。 "
#. Tag: para
#, no-c-format
msgid "<literal>LockMode.READ is acquired automatically when Hibernate reads data under Repeatable Read or Serializable isolation level. It can be re-acquired by explicit user request."
msgstr "当 Hibernate 在“可重复读”或者是“序列化”数据库隔离级别下读取数据的时候,锁定模式自动设置为 <literal>LockMode.READ。这种模式也可以通过用户显式指定进行设置。 "
#. Tag: para
#, no-c-format
msgid "<literal>LockMode.NONE represents the absence of a lock. All objects switch to this lock mode at the end of a Transaction. Objects associated with the session via a call to update() or saveOrUpdate() also start out in this lock mode."
msgstr "<literal>LockMode.NONE 代表无需锁定。在 Transaction 结束时, 所有的对象都切换到该模式上来。与 session 相关联的对象通过调用 update() 或者 saveOrUpdate() 脱离该模式。"
#. Tag: para
#, no-c-format
msgid "The \"explicit user request\" is expressed in one of the following ways:"
msgstr "\"显式的用户指定\"可以通过以下几种方式之一来表示:"
#. Tag: para
#, no-c-format
msgid "A call to <literal>Session.load(), specifying a LockMode."
msgstr "调用 <literal>Session.load() 的时候指定锁定模式(LockMode)。"
#. Tag: para
#, no-c-format
msgid "A call to <literal>Session.lock()."
msgstr "调用 <literal>Session.lock()。"
#. Tag: para
#, no-c-format
msgid "A call to <literal>Query.setLockMode()."
msgstr "调用 <literal>Query.setLockMode()。"
#. Tag: para
#, no-c-format
msgid "If <literal>Session.load() is called with UPGRADE or UPGRADE_NOWAIT, and the requested object was not yet loaded by the session, the object is loaded using SELECT ... FOR UPDATE. If load() is called for an object that is already loaded with a less restrictive lock than the one requested, Hibernate calls lock() for that object."
msgstr "如果在 <literal>UPGRADE 或者 UPGRADE_NOWAIT 锁定模式下调用 Session.load(),并且要读取的对象尚未被 session 载入过,那么对象通过 SELECT ... FOR UPDATE 这样的 SQL 语句被载入。如果为一个对象调用 load() 方法时,该对象已经在另一个较少限制的锁定模式下被载入了,那么 Hibernate 就对该对象调用 lock() 方法。"
#. Tag: para
#, no-c-format
msgid "<literal>Session.lock() performs a version number check if the specified lock mode is READ, UPGRADE or UPGRADE_NOWAIT. In the case of UPGRADE or UPGRADE_NOWAIT, SELECT ... FOR UPDATE is used."
msgstr "如果指定的锁定模式是 <literal>READ,UPGRADE 或 UPGRADE_NOWAIT,那么 Session.lock() 就执行版本号检查。(在 UPGRADE 或者 UPGRADE_NOWAIT 锁定模式下,执行 SELECT ... FOR UPDATE这样的SQL语句。)"
#. Tag: para
#, no-c-format
msgid "If the requested lock mode is not supported by the database, Hibernate uses an appropriate alternate mode instead of throwing an exception. This ensures that applications are portable."
msgstr "如果数据库不支持用户设置的锁定模式,Hibernate 将使用适当的替代模式(而不是扔出异常)。这一点可以确保应用程序的可移植性。 "
#. Tag: title
#, no-c-format
msgid "Connection release modes"
msgstr "连接释放模式(Connection Release Modes) "
#. Tag: para
#, no-c-format
msgid "One of the legacies of Hibernate 2.x JDBC connection management meant that a <literal>Session would obtain a connection when it was first required and then maintain that connection until the session was closed. Hibernate 3.x introduced the notion of connection release modes that would instruct a session how to handle its JDBC connections. The following discussion is pertinent only to connections provided through a configured ConnectionProvider. User-supplied connections are outside the breadth of this discussion. The different release modes are identified by the enumerated values of org.hibernate.ConnectionReleaseMode:"
msgstr "Hibernate 关于 JDBC 连接管理的旧(2.x)行为是,<literal>Session 在第一次需要的时候获取一个连接,在 session 关闭之前一直会持有这个连接。Hibernate 引入了连接释放的概念,来告诉 session 如何处理它的 JDBC 连接。注意,下面的讨论只适用于采用配置 ConnectionProvider 来提供连接的情况,用户自己提供的连接与这里的讨论无关。通过 org.hibernate.ConnectionReleaseMode 的不同枚举值来使用不用的释放模式:"
#. Tag: para
#, no-c-format
msgid "<literal>ON_CLOSE: is the legacy behavior described above. The Hibernate session obtains a connection when it first needs to perform some JDBC access and maintains that connection until the session is closed."
msgstr "<literal>ON_CLOSE:基本上就是上面提到的老式行为。Hibernate session 在第一次需要进行 JDBC 操作的时候获取连接,然后持有它,直到 session 关闭。"
#. Tag: para
#, no-c-format
msgid "<literal>AFTER_TRANSACTION: releases connections after a org.hibernate.Transaction has been completed."
msgstr "<literal>AFTER_TRANSACTION:在 org.hibernate.Transaction 结束后释放连接。"
#. Tag: para
#, no-c-format
msgid "<literal>AFTER_STATEMENT (also referred to as aggressive release): releases connections after every statement execution. This aggressive releasing is skipped if that statement leaves open resources associated with the given session. Currently the only situation where this occurs is through the use of org.hibernate.ScrollableResults."
msgstr "<literal>AFTER_STATEMENT(也被称做积极释放):在每一条语句被执行后就释放连接。但假若语句留下了与 session 相关的资源,那就不会被释放。目前唯一的这种情形就是使用 org.hibernate.ScrollableResults。"
#. Tag: para
#, no-c-format
msgid "The configuration parameter <literal>hibernate.connection.release_mode is used to specify which release mode to use. The possible values are as follows:"
msgstr "<literal>hibernate.connection.release_mode 配置参数用来指定使用哪一种释放模式。可能的值有: "
#. Tag: para
#, no-c-format
msgid "<literal>auto (the default): this choice delegates to the release mode returned by the org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode() method. For JTATransactionFactory, this returns ConnectionReleaseMode.AFTER_STATEMENT; for JDBCTransactionFactory, this returns ConnectionReleaseMode.AFTER_TRANSACTION. Do not change this default behavior as failures due to the value of this setting tend to indicate bugs and/or invalid assumptions in user code."
msgstr "<literal>auto(默认):这一选择把释放模式委派给 org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode() 方法。对 JTATransactionFactory 来说,它会返回 ConnectionReleaseMode.AFTER_STATEMENT;对 JDBCTransactionFactory 来说,则是ConnectionReleaseMode.AFTER_TRANSACTION。很少需要修改这一默认行为,因为假若设置不当,就会带来 bug,或者给用户代码带来误导。"
#. Tag: para
#, no-c-format
msgid "<literal>on_close: uses ConnectionReleaseMode.ON_CLOSE. This setting is left for backwards compatibility, but its use is discouraged."
msgstr "<literal>on_close:使用 ConnectionReleaseMode.ON_CLOSE。这种方式是为了向下兼容的,但是已经完全不被鼓励使用了。"
#. Tag: para
#, no-c-format
msgid "<literal>after_transaction: uses ConnectionReleaseMode.AFTER_TRANSACTION. This setting should not be used in JTA environments. Also note that with ConnectionReleaseMode.AFTER_TRANSACTION, if a session is considered to be in auto-commit mode, connections will be released as if the release mode were AFTER_STATEMENT."
msgstr "<literal>after_transaction:使用 ConnectionReleaseMode.AFTER_TRANSACTION。这一设置不应该在 JTA 环境下使用。也要注意,使用 ConnectionReleaseMode.AFTER_TRANSACTION 的时候,假若session 处于 auto-commit 状态,连接会像 AFTER_STATEMENT 那样被释放。"
#. Tag: para
#, no-c-format
msgid "<literal>after_statement: uses ConnectionReleaseMode.AFTER_STATEMENT. Additionally, the configured ConnectionProvider is consulted to see if it supports this setting (supportsAggressiveRelease()). If not, the release mode is reset to ConnectionReleaseMode.AFTER_TRANSACTION. This setting is only safe in environments where we can either re-acquire the same underlying JDBC connection each time you make a call into ConnectionProvider.getConnection() or in auto-commit environments where it does not matter if we re-establish the same connection."
msgstr "<literal>after_statement:使用 ConnectionReleaseMode.AFTER_STATEMENT。除此之外,会查询配置的 ConnectionProvider,是否它支持这一设置(supportsAggressiveRelease())。假若不支持,释放模式会被设置为 ConnectionReleaseMode.AFTER_TRANSACTION。只有在你每次调用 ConnectionProvider.getConnection() 获取底层 JDBC 连接的时候,都可以确信获得同一个连接的时候,这一设置才是安全的;或者在 auto-commit 环境中,你可以不管是否每次都获得同一个连接的时候,这才是安全的。"
#~ msgid "foo==bar"
#~ msgstr "foo==bar"
#~ msgid ""
#~ "<![CDATA[// Non-managed environment idiom\n"
#~ "Session sess = factory.openSession();\n"
#~ "Transaction tx = null;\n"
#~ "try {\n"
#~ " tx = sess.beginTransaction();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " tx.commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " if (tx != null) tx.rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}\n"
#~ "finally {\n"
#~ " sess.close();\n"
#~ "}]]>"
#~ msgstr ""
#~ "<![CDATA[// Non-managed environment idiom\n"
#~ "Session sess = factory.openSession();\n"
#~ "Transaction tx = null;\n"
#~ "try {\n"
#~ " tx = sess.beginTransaction();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " tx.commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " if (tx != null) tx.rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}\n"
#~ "finally {\n"
#~ " sess.close();\n"
#~ "}]]>"
#~ msgid ""
#~ "<![CDATA[// Non-managed environment idiom with getCurrentSession()\n"
#~ "try {\n"
#~ " factory.getCurrentSession().beginTransaction();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " factory.getCurrentSession().getTransaction().commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " factory.getCurrentSession().getTransaction().rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}]]>"
#~ msgstr ""
#~ "<![CDATA[// Non-managed environment idiom with getCurrentSession()\n"
#~ "try {\n"
#~ " factory.getCurrentSession().beginTransaction();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " factory.getCurrentSession().getTransaction().commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " factory.getCurrentSession().getTransaction().rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}]]>"
#~ msgid ""
#~ "<![CDATA[// BMT idiom\n"
#~ "Session sess = factory.openSession();\n"
#~ "Transaction tx = null;\n"
#~ "try {\n"
#~ " tx = sess.beginTransaction();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " tx.commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " if (tx != null) tx.rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}\n"
#~ "finally {\n"
#~ " sess.close();\n"
#~ "}]]>"
#~ msgstr ""
#~ "<![CDATA[// BMT idiom\n"
#~ "Session sess = factory.openSession();\n"
#~ "Transaction tx = null;\n"
#~ "try {\n"
#~ " tx = sess.beginTransaction();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " tx.commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " if (tx != null) tx.rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}\n"
#~ "finally {\n"
#~ " sess.close();\n"
#~ "}]]>"
#~ msgid ""
#~ "<![CDATA[// BMT idiom with getCurrentSession()\n"
#~ "try {\n"
#~ " UserTransaction tx = (UserTransaction)new InitialContext()\n"
#~ " .lookup(\"java:comp/UserTransaction\");\n"
#~ "\n"
#~ " tx.begin();\n"
#~ "\n"
#~ " // Do some work on Session bound to transaction\n"
#~ " factory.getCurrentSession().load(...);\n"
#~ " factory.getCurrentSession().persist(...);\n"
#~ "\n"
#~ " tx.commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " tx.rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}]]>"
#~ msgstr ""
#~ "<![CDATA[// BMT idiom with getCurrentSession()\n"
#~ "try {\n"
#~ " UserTransaction tx = (UserTransaction)new InitialContext()\n"
#~ " .lookup(\"java:comp/UserTransaction\");\n"
#~ "\n"
#~ " tx.begin();\n"
#~ "\n"
#~ " // Do some work on Session bound to transaction\n"
#~ " factory.getCurrentSession().load(...);\n"
#~ " factory.getCurrentSession().persist(...);\n"
#~ "\n"
#~ " tx.commit();\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " tx.rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}]]>"
#~ msgid ""
#~ "<![CDATA[// CMT idiom\n"
#~ " Session sess = factory.getCurrentSession();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "]]>"
#~ msgstr ""
#~ "<![CDATA[// CMT idiom\n"
#~ " Session sess = factory.getCurrentSession();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "]]>"
#~ msgid ""
#~ "<![CDATA[\n"
#~ "Session sess = factory.openSession();\n"
#~ "try {\n"
#~ " //set transaction timeout to 3 seconds\n"
#~ " sess.getTransaction().setTimeout(3);\n"
#~ " sess.getTransaction().begin();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " sess.getTransaction().commit()\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " sess.getTransaction().rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}\n"
#~ "finally {\n"
#~ " sess.close();\n"
#~ "}]]>"
#~ msgstr ""
#~ "<![CDATA[\n"
#~ "Session sess = factory.openSession();\n"
#~ "try {\n"
#~ " //set transaction timeout to 3 seconds\n"
#~ " sess.getTransaction().setTimeout(3);\n"
#~ " sess.getTransaction().begin();\n"
#~ "\n"
#~ " // do some work\n"
#~ " ...\n"
#~ "\n"
#~ " sess.getTransaction().commit()\n"
#~ "}\n"
#~ "catch (RuntimeException e) {\n"
#~ " sess.getTransaction().rollback();\n"
#~ " throw e; // or display error message\n"
#~ "}\n"
#~ "finally {\n"
#~ " sess.close();\n"
#~ "}]]>"
#~ msgid ""
#~ "<![CDATA[// foo is an instance loaded by a previous Session\n"
#~ "session = factory.openSession();\n"
#~ "Transaction t = session.beginTransaction();\n"
#~ "\n"
#~ "int oldVersion = foo.getVersion();\n"
#~ "session.load( foo, foo.getKey() ); // load the current state\n"
#~ "if ( oldVersion != foo.getVersion() ) throw new StaleObjectStateException"
#~ "();\n"
#~ "foo.setProperty(\"bar\");\n"
#~ "\n"
#~ "t.commit();\n"
#~ "session.close();]]>"
#~ msgstr ""
#~ "<![CDATA[// foo is an instance loaded by a previous Session\n"
#~ "session = factory.openSession();\n"
#~ "Transaction t = session.beginTransaction();\n"
#~ "\n"
#~ "int oldVersion = foo.getVersion();\n"
#~ "session.load( foo, foo.getKey() ); // load the current state\n"
#~ "if ( oldVersion != foo.getVersion() ) throw new StaleObjectStateException"
#~ "();\n"
#~ "foo.setProperty(\"bar\");\n"
#~ "\n"
#~ "t.commit();\n"
#~ "session.close();]]>"
#~ msgid ""
#~ "<![CDATA[// foo is an instance loaded earlier by the old session\n"
#~ "Transaction t = session.beginTransaction(); // Obtain a new JDBC "
#~ "connection, start transaction\n"
#~ "\n"
#~ "foo.setProperty(\"bar\");\n"
#~ "\n"
#~ "session.flush(); // Only for last transaction in conversation\n"
#~ "t.commit(); // Also return JDBC connection\n"
#~ "session.close(); // Only for last transaction in conversation]]>"
#~ msgstr ""
#~ "<![CDATA[// foo is an instance loaded earlier by the old session\n"
#~ "Transaction t = session.beginTransaction(); // Obtain a new JDBC "
#~ "connection, start transaction\n"
#~ "\n"
#~ "foo.setProperty(\"bar\");\n"
#~ "\n"
#~ "session.flush(); // Only for last transaction in conversation\n"
#~ "t.commit(); // Also return JDBC connection\n"
#~ "session.close(); // Only for last transaction in conversation]]>"
#~ msgid ""
#~ "<![CDATA[// foo is an instance loaded by a previous Session\n"
#~ "foo.setProperty(\"bar\");\n"
#~ "session = factory.openSession();\n"
#~ "Transaction t = session.beginTransaction();\n"
#~ "session.saveOrUpdate(foo); // Use merge() if \"foo\" might have been "
#~ "loaded already\n"
#~ "t.commit();\n"
#~ "session.close();]]>"
#~ msgstr ""
#~ "<![CDATA[// foo is an instance loaded by a previous Session\n"
#~ "foo.setProperty(\"bar\");\n"
#~ "session = factory.openSession();\n"
#~ "Transaction t = session.beginTransaction();\n"
#~ "session.saveOrUpdate(foo); // Use merge() if \"foo\" might have been "
#~ "loaded already\n"
#~ "t.commit();\n"
#~ "session.close();]]>"
Other Hibernate examples (source code examples)
Here is a short list of links related to this Hibernate transactions.po source code file: