問題
- 以下のエラーにより Group import 方式で LDAP ユーザーをインポートできない場合、データベースの Users_UserGroups テーブルに、孤立したエントリが存在する可能性があります。:
com.liferay.portal.kernel.exception.NoSuchUserException: No User exists with the primary key NNNNNNNN
環境
- Liferay DXP 7.4
解決
-
Users_UserGroupsテーブルは、ユーザをそのユーザが所属するユーザー・グループにマッピングします。
LDAP グループのインポートが失敗する場合は、データベースに存在しないユーザーを指す孤立したデータがこのテーブルに存在する可能性が高くなります。グループ インポート ログの例を次に示します:com.liferay.portal.kernel.exception.NoSuchUserException: No User exists with the primary key NNNNNNNN
これは、Users_UserGroupsテーブルに、 NNNNNNという userId を持つエントリ(またはエントリ)が存在することを意味しますが、User_テーブルに対応するエントリは存在しません。 これが、例外につながります。 インポート処理中、LiferayはインポートされたLDAPグループのメンバーであるすべてのユーザーを検索しようとします。 このため、Users_UserGroupsテーブルに問い合わせが行われ、最終的にこのExceptionが発生します。
この情報は、Users_UserGroupsテーブルに、以下のようなクエリを実行して、孤立したデータが存在しないかどうかを確認することで確認できます:SELECT * FROM Users_UserGroups WHERE userId NOT IN (SELECT userId FROM User_)
- 重複するエントリーが見つかった場合、手動でそのエントリーをデータベースから削除しないことを強くお勧めします。 代わりに、コントロールパネル > サーバー管理 > スクリプト から、次のGroovyスクリプトを実行できます。
注意:このスクリプトを実行する前に、Liferay環境、関連データベース、ドキュメントリポジトリのバックアップを作成するために、サーバーをシャットダウンすることを確認してください。 これは、何らかの問題が発生した場合に、復元ポイントを確保するためです。 完了後、サーバーを再起動し、Scriptコンソールに入り、以下のスクリプトを実行してください。
import com.liferay.portal.kernel.dao.jdbc.AutoBatchPreparedStatementUtil;
import com.liferay.portal.kernel.dao.jdbc.DataAccess;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DeleteOrphanedUsersUserGroupsData {
public void doDeleteOrphanedUsersUserGroupsData() {
Connection con = null;
PreparedStatement ps1 = null;
PreparedStatement ps2 = null;
ResultSet rs = null;
try {
con = DataAccess.getConnection();
ps1 = con.prepareStatement(
"select distinct(userId) from Users_UserGroups where userId " +
"not in (select userId from User_)");
ps2 = AutoBatchPreparedStatementUtil.concurrentAutoBatch(
con, "delete from Users_UserGroups where userId = ?");
rs = ps1.executeQuery();
while (rs.next()) {
long userId = rs.getLong("userId");
if (_log.isInfoEnabled()) {
_log.info(
"Found orphaned user id " + userId + " in " +
"Users_UserGroups table. Queuing entries with " +
"this user id for deletion.");
}
ps2.setLong(1, userId);
ps2.addBatch();
}
ps2.executeBatch();
if (_log.isInfoEnabled()) {
_log.info("Successfully executed all queued deletions");
}
}
catch (Exception e) {
_log.error("Error while executing script", e);
}
finally {
DataAccess.cleanUp(ps1);
DataAccess.cleanUp(con, ps2, rs);
}
}
private static Log _log = LogFactoryUtil.getLog(
DeleteOrphanedUsersUserGroupsData.class);
}
out.println(
"Running groovy script to delete orphaned data from the Users_UserGroups " +
"table...");
DeleteOrphanedUsersUserGroupsData deleteOrphanedUsersUserGroupsData =
new DeleteOrphanedUsersUserGroupsData();
deleteOrphanedUsersUserGroupsData.doDeleteOrphanedUsersUserGroupsData();
out.println("Script finished running.");
この作業が完了したら、再度グループインポートを実行し、この動作が解決されることを確認してください。
追加情報