質問

I am using spring-data-jpa and JPA repositories

here is my source code

<beans:bean id="producerService" class="cz.services.RepositoryProducerService" />
<jpa:repositories base-package="cz.repository" />

<beans:bean id="myEmf"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <beans:property name="dataSource" ref="dataSource" />
    <beans:property name="packagesToScan" value="cz.models" />
    <beans:property name="jpaVendorAdapter">
        <beans:bean
            class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </beans:property>
    <beans:property name="jpaProperties">
        <beans:props>

            <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
            </beans:prop>
            <beans:prop key="hibernate.show_sql">true</beans:prop>
        </beans:props>
    </beans:property>
</beans:bean>

<beans:bean id="transactionManager"
    class="org.springframework.orm.jpa.JpaTransactionManager">
    <beans:property name="entityManagerFactory" ref="myEmf" />
</beans:bean>

<beans:bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <beans:property name="url"
        value="jdbc:mysql://localhost:3306/mydb?zeroDateTimeBehavior=convertToNull&amp;characterEncoding=UTF-8" />

    <beans:property name="username" value="root" />
    <!--<property name="password" value="test" /> -->
    <beans:property name="password" value="test"></beans:property>
</beans:bean>

and here is my entity and repository classes:

package cz.models;

import java.io.Serializable;
import javax.persistence.*;
import java.util.List;


/**
 * The persistent class for the users database table.
 * 
 */
@Entity
@Table(name="users")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    private int enabled;

    private String password;

    private String username;

    //bi-directional many-to-one association to Authority
    @OneToMany(mappedBy="user")
    private List<Authority> authorities;

    //bi-directional many-to-one association to Room
    @OneToMany(mappedBy="user")
    private List<Room> rooms;

    //bi-directional many-to-one association to UsersData
    @OneToMany(mappedBy="user")
    private List<UsersData> usersData;

    public User() {
    }

    ....

    public List<Room> getRooms() {
        return this.rooms;
    }

and here are User Repository:

    public void setRooms(List<Room> rooms) {
        this.rooms = rooms;
    }

    public Room addRoom(Room room) {
        getRooms().add(room);
        room.setUser(this);

        return room;
    }

    public Room removeRoom(Room room) {
        getRooms().remove(room);
        room.setUser(null);

        return room;
    }

    public List<UsersData> getUsersData() {
        return this.usersData;
    }

    public void setUsersData(List<UsersData> usersData) {
        this.usersData = usersData;
    }

    public UsersData addUsersData(UsersData usersData) {
        getUsersData().add(usersData);
        usersData.setUser(this);

        return usersData;
    }

    public UsersData removeUsersData(UsersData usersData) {
        getUsersData().remove(usersData);
        usersData.setUser(null);

        return usersData;
    }

}

and userRepository:

public interface UserRepository extends JpaRepository<User, Integer> {
    @Transactional
    @Query("select u from User u WHERE u.enabled = 1 ")
    public List<User> findAllactiveUsers();
    @Transactional
    @Query("select u from User u WHERE u.username = :username ")
    public User findByUsername(@Param("username")String username);
}

and my service for spring security:

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Resource
    UserRepository repositoryUser;
    @Resource
    AuthorityRepository repositoryAuthority;

    public UserDetails loadUserByUsername(String username) {
        System.out.println("start");
        cz.models.User userModel = null;
        UserDetails userDetail = null;
        try{
            userModel = repositoryUser.findByUsername(username);

        // User user = userModel;
        System.out.println(userModel.getUsername());

        List<Authority> authorities = repositoryAuthority.findAllByUser(userModel);
//      repositoryUserData.findAll();
        System.out.println(userModel.getAuthorities().size());
        Collection<SimpleGrantedAuthority> collectionAuthorities = new ArrayList<SimpleGrantedAuthority>();
        for (int i = 0; i < authorities.size(); i++) {
            collectionAuthorities.add(new SimpleGrantedAuthority(authorities
                    .get(i).getAuthority()));
        }

         userDetail = new User(userModel.getUsername(),
                userModel.getUsername(), collectionAuthorities);
        }catch(Exception e){
            e.printStackTrace();
        }
        return userDetail;

    }
}

The problem is: when I want call - this peace of code:

userModel.getAuthorities()

which call child (fk in db). I have exception :

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

When I add second repository Authorities I do not have this no session problem. But I do not want create every time method in my repository.

List<Authority> authorities = repositoryAuthority.findAllByUser(userModel);

I have to use hibernate.LazyInitialization instead of eanger.(and some stable)

I saw a lot of post with this problem with JPA, but nothing work for me :(

役に立ちましたか?

解決

Use a query that fetches the data you want so that it is there when you need it.

@Query("select u from User u left join fetch u.authorities WHERE u.username = :username ")
public User findByUsernameFetchAuthorities(@Param("username")String username);

Using findByUsernameFetchAuthorities when you want to access the authorities will cause them to be pre-fetched, avoiding the error and keeping them lazily fetched for every other query.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top