1

Spring Data CrudRepository を使用して、c3p0 接続プールを使用して MySQL5 (InnoDB) データベースで JPA アノテーションを使用して実装された Hibernate4 ベースの永続化レイヤーにアクセスする Spring ベースの CLI アプリケーションを実行しようとしています。

次の例外が発生します。

Exception in thread "main" java.lang.RuntimeException: org.springframework.orm.hibernate3.HibernateSystemException: failed to lazily initialize a collection of role: <package>.entity.User.categories, could not initialize proxy - no Session; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: <package>.entity.User.categories, could not initialize proxy - no Session

私はSpring DataとHibernateの初心者です。私の観点からは、これは 2 つの異なるトランザクションの問題です (1 つは にUserServiceImpl::findByLogin、もう 1 つは にCategoryServiceImpl::deleteByUser)。カテゴリに Eager fetch タイプを使用するようにエンティティを変更Userすると役立ちますが、このメソッドでは遅延読み込みを使用したいと考えています。

サービスレイヤーでSpring管理のトランザクションを使用UserServiceImpl::findByLoginして、後でサービスコンシューマーで遅延フェッチタイプを使用して依存オブジェクトをフェッチすることはできますか?CrudRepository

例外を引き起こすアプリケーションからの抜粋:

    User user = userService.findByLogin(login);
    categoryService.deleteByUser(user);

編集:私は使用しようとしましEntityManager::mergeたが、運がありません:

@Service
@Repository
@Transactional
public class CategoryServiceImpl implements CategoryService, InitializingBean {

    @Autowired
    private CategoryRepository repository;

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    private EntityManager entityManager;

    @Override
    public void afterPropertiesSet() throws Exception {
        entityManager = entityManagerFactory.createEntityManager();
    }

    @Override
    @Transactional(readOnly = true)
    public Category findById(Long categoryId) {
        return repository.findOne(categoryId);
    }

    @Override
    @Transactional
    public Category save(Category category) {
        return repository.save(category);
    }

    @Override
    @Transactional
    public void delete(Category category) {
        repository.delete(category);
    }

    @Override
    @Transactional
    public void deleteByUser(User user) {
        entityManager.merge(user);
        repository.delete(user.getCategories());
    }
}

サービス ( で注入@Autowired): ユーザー サービス:

package <package>.service.jpa;

import com.google.common.collect.Lists;
import <package>.entity.User;
import <package>.repository.UserRepository;
import <package>.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Repository
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository repository;

    @Override
    @Transactional(readOnly = true)
    public List<User> findAll() {
        return Lists.newArrayList(repository.findAll());
    }

    @Override
    @Transactional(readOnly = true)
    public User findById(Long userId) {
        return repository.findOne(userId);
    }

    @Override
    @Transactional(readOnly = true)
    public User findByLogin(String login) {
        return repository.findByLogin(login);
    }

    @Override
    @Transactional
    public User save(User user) {
        return repository.save(user);
    }

    @Override
    @Transactional
    public void delete(User user) {
        repository.delete(user);
    }
}

カテゴリ サービス:

package <package>.service.jpa;

import <package>.entity.Category;
import <package>.entity.User;
import <package>.repository.CategoryRepository;
import <package>.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Repository
@Transactional
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryRepository repository;

    @Override
    @Transactional(readOnly = true)
    public Category findById(Long categoryId) {
        return repository.findOne(categoryId);
    }

    @Override
    @Transactional
    public Category save(Category category) {
        return repository.save(category);
    }

    @Override
    @Transactional
    public void delete(Category category) {
        repository.delete(category);
    }

    @Override
    @Transactional
    public void deleteByUser(User user) {
        repository.delete(user.getCategories());
    }
}

エンティティ: ユーザー:

package <package>.entity;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table
public class User {
    private Long userId;
    private int version;
    private String login;
    private Set<Category> categories = new HashSet<Category>();
    private Set<CategoryFeed> categoryFeeds = new HashSet<CategoryFeed>();

    @Id
    @GeneratedValue
    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    @Version
    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    @Column
    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    public Set<Category> getCategories() {
        return categories;
    }

    public void setCategories(Set<Category> categories) {
        this.categories = categories;
    }

    public void addCategory(Category category) {
        categories.add(category);
    }

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    public Set<CategoryFeed> getCategoryFeeds() {
        return categoryFeeds;
    }

    public void setCategoryFeeds(Set<CategoryFeed> categoryFeeds) {
        this.categoryFeeds = categoryFeeds;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof User)) {
            return false;
        }

        User user = (User) o;

        if (login != null ? !login.equals(user.login) : user.login != null) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        return login != null ? login.hashCode() : 0;
    }
}

カテゴリー:

package <package>.entity;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"userId", "title"}))
public class Category {
    public static final String ROOT_CATEGORY_TITLE = "";

    private Long categoryId;
    private int version;
    private User user;
    private String title = ROOT_CATEGORY_TITLE;

    private Set<CategoryFeed> feeds = new HashSet<CategoryFeed>();

    @Id
    @GeneratedValue
    public Long getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(Long categoryId) {
        this.categoryId = categoryId;
    }

    @Version
    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    @ManyToOne
    @JoinColumn(name = "userId")
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Column(name = "title")
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @ManyToMany(mappedBy = "categories", cascade = CascadeType.ALL)
    public Set<CategoryFeed> getFeeds() {
        return feeds;
    }

    public void setFeeds(Set<CategoryFeed> feeds) {
        this.feeds = feeds;
    }

    public void addFeed(CategoryFeed feed) {
        this.feeds.add(feed);
    }

    @Override
    public boolean equals(Object o) {

        if (this == o) {
            return true;
        }
        if (!(o instanceof Category)) {
            return false;
        }

        Category category = (Category) o;

        if (title != null ? !title.equals(category.title) : category.title != null) {
            return false;
        }
        if (user != null ? !user.equals(category.user) : category.user != null) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = user != null ? user.hashCode() : 0;
        result = 31 * result + (title != null ? title.hashCode() : 0);
        return result;
    }
}
4

2 に答える 2