私はHibernate 2nd EditionでJava Persistenceを読んでいます。私は私がはっきりしない本から下の引用を見つけました。Hibernateのダーティチェックのクエリ
もう1つの問題は、汚れチェックです。自動的にHibernate は、更新された状態をデータベース と同期させるために状態の変化を検出します。通常、Hibernateによってsetterに渡されたインスタンスよりも、getterメソッドの から別のインスタンスを返すことは安全です。 Hibernateは、オブジェクトのIDではなく値を比較して、 の属性の永続状態を更新する必要があるかどうかを判断します。 たとえば、次のgetterメソッドは、不必要なSQL アップデートでなりません。
public String getFirstName(){
return new String(firstName);
}
私の質問新しいStringオブジェクトを返すことは、不必要なSQLの更新をすることはありません理由で、どのようにちょうど戻ってからも異なっていますファーストネーム?
getFirstNameを実行しようとすると、更新クエリが実行されませんでした。
私には分かりませんが、教えてください。
以下コードです:データベースに仮定
package org.prashdeep.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class User {
protected Long id;
@Id
@GeneratedValue()
public Long getId() { // Optional but useful
return id;
}
protected String firstName;
protected String lastName;
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
System.out.println("Called from the setter of lastname");
this.lastName = lastName;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
SaveUserEntity.java
package org.prashdeep.executor;
import bitronix.tm.resource.jdbc.PoolingDataSource;
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.prashdeep.common.DatabaseProduct;
import org.prashdeep.model.User;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import java.util.List;
public class SaveUserEntity {
protected Context context;
protected PoolingDataSource dataSource;
public static String DATASOURCE_NAME = "myDS";
public DatabaseProduct databaseProduct;
public UserTransaction getUserTransaction() {
try {
return (UserTransaction) context.lookup("java:comp/UserTransaction");
} 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);
}
}
protected SessionFactory createSessionFactory() throws Exception{
this.dataSource = new PoolingDataSource();
dataSource.setUniqueName(DATASOURCE_NAME);
dataSource.setMinPoolSize(1);
dataSource.setMaxPoolSize(5);
dataSource.setPreparedStatementCacheSize(10);
dataSource.setIsolationLevel("READ_COMMITTED");
dataSource.setClassName("org.h2.jdbcx.JdbcDataSource");
dataSource.setAllowLocalTransactions(true);
dataSource.getDriverProperties().put(
"URL",
"jdbc:h2:mem:test"
);
dataSource.getDriverProperties().put("user", "sa");
context = new InitialContext();
dataSource.init();
/*
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.show_sql", "true")
.applySetting("hibernate.hbm2ddl.auto", "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.prashdeep.model.User.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();
SessionFactory sessionFactory = metadata.buildSessionFactory();
return sessionFactory;
}
public static void main(String args[]) throws Exception {
SaveUserEntity obj = new SaveUserEntity();
SessionFactory sessionFactory = obj.createSessionFactory();
try {
{
/*
Get access to the standard transaction API <code>UserTransaction</code> and
begin a transaction on this thread of execution.
*/
UserTransaction tx = obj.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();
User user = new User();
user.setFirstName("Pradeep");
user.setLastName("Kumar");
/*
The native Hibernate API is very similar to the standard Java Persistence API and most methods
have the same name.
*/
session.persist(user);
/*
Hibernate synchronizes the session with the database and closes the "current"
session on commit of the bound transaction automatically.
*/
tx.commit();
}
{
UserTransaction tx = obj.getUserTransaction();
tx.begin();
/*
A Hibernate criteria query is a type-safe programmatic way to express queries,
automatically translated into SQL.
*/
List<User> users =
sessionFactory.getCurrentSession().createCriteria(
User.class
).list();
// SELECT * from MESSAGE
users.get(0).setFirstName("Praveen");
System.out.println(users.get(0).getFirstName());
tx.commit();
}
} finally {
obj.rollback();
}
}
}
答えをくれてありがとう。しかし、この例のように、新しいStringオブジェクトを返すことはSQLの更新を避けることができます。私は何かが足りない。私が試してみる疑似コードを表示してください。 – zilcuanu
更新を避けない*更新を引き起こさない*更新は、現在の永続エンティティのプロパティがデータベース内のものと等しくない場合にのみ発生します。この例は、 'equal'値を持つ別のオブジェクトが更新を起こさないことを実証するための人工的な例です。 – geert3
実際には心配する必要はありません。 – geert3