通过spring数据和f:viewAction加载实体然后访问其中一个属性时的lazyload异常

问题描述 投票:0回答:1

我正在为我的项目使用JSF,spring boot和spring数据。我正在尝试编辑现有对象。为此,我将对象id作为参数传递给视图,然后指定f:viewAction,它在数据库中查找并加载对象。我得到的是“无法初始化代理..没有会话”Lazyloadexception稍后,在一个不同的方法中,当在该SAME对象上调用一个简单的getter时(我通过id得到的同一个对象,而不是一个内部的对象)收集或任何东西)。

我试过了:

  • 将@Transactional放在JSF bean类和DAO类上
  • 将@Transactional放在从f:viewAction调用的onload方法和对象的getter方法上。
  • 把spring.jpa.properties.hibernate.enable_lazy_load_no_trans = true放在我的application.properties中(是的,我知道,反模式,但使用反模式的工作应用程序比完全不工作的应用程序更好。无论如何,它什么也没做)
  • 将@EnableTransactionManagement放在扩展SpringBootServletInitializer的安装类上
  • 将@EnableTransactionManagement放在PersistenceConfig类上

基本上,我可以通过谷歌搜索此错误的几小时和几小时找到的每个“解决方案”。我不知道此时该做什么。我有一种感觉这与加载顺序有关,而DAO调用则在f:viewAction方法中。也许使用不同的会话,通过方法访问对象的任何东西?

很抱歉包括很多部分,我只是不知道根本原因在哪里。我怀疑它是Spring数据,JPA和JSF的相互作用。

当我尝试使用@PostConstruct注释在数据库中调用初始化对象时,我遇到了同样的错误。我“解决”(读取:修补)的方式是在getter内部进行数据库调用,这是dumb(if(myobject == null)执行db调用。else return myobject)

错误:

org.hibernate.LazyInitializationException: could not initialize proxy [mypackage.recipe.RecipeItem#8] - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
    at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
    at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
    at mypackage.recipe.RecipeItem$HibernateProxy$G4ytmgbe.getDisplayName(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)


@EnableJpaRepositories(basePackages = "mypackage")
@EnableTransactionManagement
public class PersistenceConfig
{
    // nothing here
}

@SpringBootApplication(scanBasePackages={"mypackage"})
@EnableJpaRepositories(basePackages = "mypackage")
@EnableTransactionManagement
public class SpringBootTomcatApplication extends SpringBootServletInitializer {
    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter bean = new HibernateJpaVendorAdapter();
        bean.setDatabase(Database.MYSQL);
        bean.setGenerateDdl(true);
        bean.setShowSql(true);
        return bean;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
            JpaVendorAdapter jpaVendorAdapter) {
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(dataSource);
        bean.setJpaVendorAdapter(jpaVendorAdapter);
        bean.setPackagesToScan("mypackage");
        return bean;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}

@Component
@Transactional
@Scope("session")
public class EditRecipeItemControllerBean extends RecipeItemControllerBean
{
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Transactional
    public void onload() {
        Map<String,String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        String recipeId = params.get("recipeId");
        log.info("from context recipe id: " + recipeId);
        //TODO error handling
        setRecipe(recipeDao.getOne(Long.valueOf(recipeId)));
    }

    public void submit() {
        super.save();
    }
}       

public class RecipeItemControllerBean implements Serializable
{    
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    AuthenticationFacade authenticationFacade;  
    @Autowired
    RecipeItemDao recipeDao;

    private RecipeItem recipe;

    /**
     * @return the recipe
     */
    public RecipeItem getRecipe()
    {
        return recipe;
    }

    /**
     * @param recipe the recipe to set
     */
    public void setRecipe(RecipeItem recipe)
    {
        this.recipe = recipe;
    }

    public void save() {
        log.debug("Saving recipe: " + recipe);
        recipeDao.save(recipe);
    }
}

@Entity
@Table(name = "recipe_item")
@NamedQueries(
{
    // a bunch of named queries here
})
public class RecipeItem extends ClientSpecific
{
    @Column(length = 256)
    private String description;
    @Lob
    @Column(name = "full_info", length = 65535)
    private String fullInfo;
    @Column(name = "thumbnail_uri", length = 1024)
    private String thumbnailUri;
    @Lob
    @Column(name = "preparation_instructions", length = 65535)
    private String preparationInstructions;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "recipeItem", fetch = FetchType.EAGER)
    private Collection<RecipeItemIngredients> recipeItemIngredients;

    public RecipeItem()
    {
    }

    //getters and setters 
}

@MappedSuperclass
public abstract class ClientSpecific extends NamedBaseEntity
{    
    @JoinColumn(name = "client_id", referencedColumnName = "id")
    @ManyToOne
    private Client client;

    public ClientSpecific()
    {
    }

    public ClientSpecific(Long id)
    {
        super(id);
    }

    public ClientSpecific(Long id, Client client)
    {
        super(id);
        this.client = client;
    }

    // getters and setters clipped for brevity
}

@MappedSuperclass
public abstract class NamedBaseEntity extends BaseEntity
{
    @Size(max = 64)
    @Column(name = "display_name")
    private String displayName;

    public NamedBaseEntity()
    {
    }

    public NamedBaseEntity(Long id)
    {
        super(id);
    }
    // gettes setters and tostring
}

@MappedSuperclass
@JsonIgnoreProperties(value = {"updated", "created"})
public abstract class BaseEntity implements Serializable
{    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "created")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @Column(name = "updated")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updated;

    @Column(name = "active")
    private Short active = (short) 1;

    public BaseEntity()
    {
    }

    public BaseEntity(Long id)
    {
        this.id = id;
    }
    // getters, settes, toString, hascode and equals
}

@Repository
@Transactional
@Component
public interface RecipeItemDao extends JpaRepository<RecipeItem, Long>
{
    // methods and implementation auto-generated by Spring Data
}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>mypackage.web</groupId>
    <artifactId>CoffeeShopWebApp</artifactId>
    <version>0</version>
    <packaging>war</packaging>

    <name>CoffeeShopWebApp</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.hibernate.validator</groupId>
                    <artifactId>hibernate-validator</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mypackage.base</groupId>
            <artifactId>myapplication-module-base</artifactId>
            <version>0</version>
        </dependency>
        <dependency>
            <groupId>org.joinfaces</groupId>
            <artifactId>joinfaces-dependencies</artifactId>
            <version>4.0.2</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>6.2</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces.extensions</groupId>
            <artifactId>primefaces-extensions</artifactId>
            <version>6.2.10</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces.extensions</groupId>
            <artifactId>resources-ckeditor</artifactId>
            <version>6.2.10</version>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>myapplication-recipe</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

spring.datasource.url=jdbc:mysql://myDatabaseStuff?zeroDateTimeBehavior=convertToNull
spring.datasource.username=censored
spring.datasource.password=censored
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jmx.default-domain: censored
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.hibernate.ddl-auto=none
server.error.whitelabel.enabled=false
spring spring-boot jsf spring-data-jpa spring-data
1个回答
0
投票

我想到了。这不是我的任何交易内容,就像我认为的那样。事实上,我使用的是getOne()而不是findById()。

这是帮助我的问题/答案:

spring data jpa getOne throw LazyInitializationException and findBy not

© www.soinside.com 2019 - 2024. All rights reserved.