68

更新クエリがあります:

@Modifying
@Transactional
@Query("UPDATE Admin SET firstname = :firstname, lastname = :lastname, login = :login, superAdmin = :superAdmin, preferenceAdmin = :preferenceAdmin, address =  :address, zipCode = :zipCode, city = :city, country = :country, email = :email, profile = :profile, postLoginUrl = :postLoginUrl WHERE id = :id")
public void update(@Param("firstname") String firstname, @Param("lastname") String lastname, @Param("login") String login, @Param("superAdmin") boolean superAdmin, @Param("preferenceAdmin") boolean preferenceAdmin, @Param("address") String address, @Param("zipCode") String zipCode, @Param("city") String city, @Param("country") String country, @Param("email") String email, @Param("profile") String profile, @Param("postLoginUrl") String postLoginUrl, @Param("id") Long id);

私は統合テストでそれを使用しようとしています:

adminRepository.update("Toto", "LeHeros", admin0.getLogin(), admin0.getSuperAdmin(), admin0.getPreferenceAdmin(), admin0.getAddress(), admin0.getZipCode(), admin0.getCity(), admin0.getCountry(), admin0.getEmail(), admin0.getProfile(), admin0.getPostLoginUrl(), admin0.getId());
Admin loadedAdmin = adminRepository.findOne(admin0.getId());
assertEquals("Toto", loadedAdmin.getFirstname());
assertEquals("LeHeros", loadedAdmin.getLastname());

ただし、フィールドは更新されず、初期値が保持されるため、テストは失敗します。

findOne クエリの直前にフラッシュを追加してみました:

adminRepository.flush();

しかし、失敗したアサーションは同じままでした。

ログに update sql ステートメントが表示されます。

update admin set firstname='Toto', lastname='LeHeros', login='stephane', super_admin=0, preference_admin=0,
address=NULL, zip_code=NULL, city=NULL, country=NULL, email='stephane@thalasoft.com', profile=NULL,
post_login_url=NULL where id=2839

しかし、ログには、ファインダーに関連する可能性のある sql が表示されません。

Admin loadedAdmin = adminRepository.findOne(admin0.getId());
The finder sql statement is not making its way to the database.

何らかのキャッシュの理由で無視されますか?

次に、次のように findByEmail および findByLogin ファインダーへの呼び出しを追加するとします。

adminRepository.update("Toto", "LeHeros", "qwerty", admin0.getSuperAdmin(), admin0.getPreferenceAdmin(), admin0.getAddress(), admin0.getZipCode(), admin0.getCity(), admin0.getCountry(), admin0.getEmail(), admin0.getProfile(), admin0.getPostLoginUrl(), admin0.getId());
Admin loadedAdmin = adminRepository.findOne(admin0.getId());
Admin myadmin = adminRepository.findByEmail(admin0.getEmail());
Admin anadmin = adminRepository.findByLogin("qwerty");
assertEquals("Toto", anadmin.getFirstname());
assertEquals("Toto", myadmin.getFirstname());
assertEquals("Toto", loadedAdmin.getFirstname());
assertEquals("LeHeros", loadedAdmin.getLastname());

次に、生成されているSQLステートメントをログで確認できます。

しかし、主張:

assertEquals("Toto", myadmin.getFirstname());

トレースが同じドメイン オブジェクトが取得されたことを示していても、失敗します。

TRACE [BasicExtractor] found [1037] as column [id14_]

この他のファインダーで私を困惑させるもう 1 つのことは、1 つの Admin オブジェクトのみを返すことになっているにもかかわらず、制限 2 句が表示されることです。

1 つのドメイン オブジェクトを返すときは常に制限 1 があると思っていました。これは Spring Data に関する間違った仮定ですか?

コンソール ログに表示される SQL ステートメントを MySQL クライアントに貼り付けると、ロジックは正常に機能します。

mysql> insert into admin (version, address, city, country, email, firstname, lastname, login, password, 
-> password_salt, post_login_url, preference_admin, profile, super_admin, zip_code) values (0,
-> NULL, NULL, NULL, 'zemail@thalasoft.com039', 'zfirstname039', 'zlastname039', 'zlogin039',
-> 'zpassword039', '', NULL, 0, NULL, 1, NULL);
Query OK, 1 row affected (0.07 sec)

mysql> select * from admin;
+------+---------+---------------+--------------+-----------+--------------+---------------+-------------+------------------+---------+----------+------+---------+-------------------------+---------+----------------+
| id | version | firstname | lastname | login | password | password_salt | super_admin | preference_admin | address | zip_code | city | country | email | profile | post_login_url |
+------+---------+---------------+--------------+-----------+--------------+---------------+-------------+------------------+---------+----------+------+---------+-------------------------+---------+----------------+
| 1807 | 0 | zfirstname039 | zlastname039 | zlogin039 | zpassword039 | | 1 | 0 | NULL | NULL | NULL | NULL | zemail@thalasoft.com039 | NULL | NULL | 
+------+---------+---------------+--------------+-----------+--------------+---------------+-------------+------------------+---------+----------+------+---------+-------------------------+---------+----------------+
1 row in set (0.00 sec)

mysql> update admin set firstname='Toto', lastname='LeHeros', login='qwerty', super_admin=0, preference_admin=0, address=NULL, zip_code=NULL, city=NULL, country=NULL, email='stephane@thalasoft.com', profile=NULL, post_login_url=NULL where id=1807;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from admin; +------+---------+-----------+----------+--------+--------------+---------------+-------------+------------------+---------+----------+------+---------+------------------------+---------+----------------+
| id | version | firstname | lastname | login | password | password_salt | super_admin | preference_admin | address | zip_code | city | country | email | profile | post_login_url |
+------+---------+-----------+----------+--------+--------------+---------------+-------------+------------------+---------+----------+------+---------+------------------------+---------+----------------+
| 1807 | 0 | Toto | LeHeros | qwerty | zpassword039 | | 0 | 0 | NULL | NULL | NULL | NULL | stephane@thalasoft.com | NULL | NULL | 
+------+---------+-----------+----------+--------+--------------+---------------+-------------+------------------+---------+----------+------+---------+------------------------+---------+----------------+
1 row in set (0.00 sec)

mysql> select admin0_.id as id14_, admin0_.version as version14_, admin0_.address as address14_, admin0_.city as city14_, admin0_.country as country14_, admin0_.email as email14_, admin0_.firstname as firstname14_, admin0_.lastname as lastname14_, admin0_.login as login14_, admin0_.password as password14_, admin0_.password_salt as password11_14_, admin0_.post_login_url as post12_14_, admin0_.preference_admin as preference13_14_, admin0_.profile as profile14_, admin0_.super_admin as super15_14_, admin0_.zip_code as zip16_14_ from admin admin0_ where admin0_.email='stephane@thalasoft.com' limit 2;
+-------+------------+------------+---------+------------+------------------------+--------------+-------------+----------+--------------+----------------+------------+------------------+------------+-------------+-----------+
| id14_ | version14_ | address14_ | city14_ | country14_ | email14_ | firstname14_ | lastname14_ | login14_ | password14_ | password11_14_ | post12_14_ | preference13_14_ | profile14_ | super15_14_ | zip16_14_ |
+-------+------------+------------+---------+------------+------------------------+--------------+-------------+----------+--------------+----------------+------------+------------------+------------+-------------+-----------+
| 1807 | 0 | NULL | NULL | NULL | stephane@thalasoft.com | Toto | LeHeros | qwerty | zpassword039 | | NULL | 0 | NULL | 0 | NULL | 
+-------+------------+------------+---------+------------+------------------------+--------------+-------------+----------+--------------+----------------+------------+------------------+------------+-------------+-----------+
1 row in set (0.00 sec)

mysql> select admin0_.id as id14_, admin0_.version as version14_, admin0_.address as address14_, admin0_.city as city14_, admin0_.country as country14_, admin0_.email as email14_, admin0_.firstname as firstname14_, admin0_.lastname as lastname14_, admin0_.login as login14_, admin0_.password as password14_, admin0_.password_salt as password11_14_, admin0_.post_login_url as post12_14_, admin0_.preference_admin as preference13_14_, admin0_.profile as profile14_, admin0_.super_admin as super15_14_, admin0_.zip_code as zip16_14_ from admin admin0_ where admin0_.login='qwerty' limit 2;
+-------+------------+------------+---------+------------+------------------------+--------------+-------------+----------+--------------+----------------+------------+------------------+------------+-------------+-----------+
| id14_ | version14_ | address14_ | city14_ | country14_ | email14_ | firstname14_ | lastname14_ | login14_ | password14_ | password11_14_ | post12_14_ | preference13_14_ | profile14_ | super15_14_ | zip16_14_ |
+-------+------------+------------+---------+------------+------------------------+--------------+-------------+----------+--------------+----------------+------------+------------------+------------+-------------+-----------+
| 1807 | 0 | NULL | NULL | NULL | stephane@thalasoft.com | Toto | LeHeros | qwerty | zpassword039 | | NULL | 0 | NULL | 0 | NULL | 
+-------+------------+------------+---------+------------+------------------------+--------------+-------------+----------+--------------+----------------+------------+------------------+------------+-------------+-----------+
1 row in set (0.00 sec)

では、なぜこれが Java レベルに反映されないのでしょうか?

4

5 に答える 5

16

何が起こっているのか、ようやく理解できました。

オブジェクトを保存するステートメントで統合テストを作成する場合は、エンティティ マネージャーをフラッシュして、偽陰性を回避することをお勧めします。つまり、テストは正常に実行されているが、運用環境で実行すると操作が失敗することを回避します。実際、最初のレベルのキャッシュがフラッシュされておらず、データベースに書き込みがヒットしていないという理由だけで、テストが正常に実行される場合があります。この偽陰性の統合テストを回避するには、テスト本体で明示的なフラッシュを使用します。いつフラッシュするかを決定するのは ORM の役割であるため、運用コードでは明示的なフラッシュを使用する必要がないことに注意してください。

update ステートメントで統合テストを作成する場合、最初のレベルのキャッシュをリロードするために、エンティティ マネージャーをクリアする必要がある場合があります。実際、更新ステートメントは一次キャッシュを完全にバイパスし、データベースに直接書き込みます。その後、第 1 レベルのキャッシュは同期されなくなり、更新されたオブジェクトの古い値が反映されます。このオブジェクトの古い状態を回避するには、テスト本体で明示的なクリアを使用します。いつクリアするかを決定するのは ORM の役割であるため、プロダクション コードでは明示的なクリアを使用する必要がないことに注意してください。

私のテストは問題なく動作するようになりました。

于 2013-06-28T22:38:18.697 に答える