Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用SpringRoo项目并获取org.hibernate.LazyInitializationException:无法初始化代理-无会话_Hibernate_Spring Roo_Spring Orm - Fatal编程技术网

使用SpringRoo项目并获取org.hibernate.LazyInitializationException:无法初始化代理-无会话

使用SpringRoo项目并获取org.hibernate.LazyInitializationException:无法初始化代理-无会话,hibernate,spring-roo,spring-orm,Hibernate,Spring Roo,Spring Orm,Edit5: 用于探索此问题解决方案的代码位于bitbucket上: 我意识到还有很多其他的LazyInitializationException帖子,但是我无法从他们那里得到我需要的信息 涉及的项目包括: memdrill数据 数据使用 memdrill数据是Spring Roo管理的项目。这里没有web组件。我只是: persistence setup --provider HIBERNATE --database HYPERSONIC_PERSISTENT 并添加了一些实体。例如:

Edit5:

用于探索此问题解决方案的代码位于bitbucket上:


我意识到还有很多其他的LazyInitializationException帖子,但是我无法从他们那里得到我需要的信息

涉及的项目包括:

  • memdrill数据
  • 数据使用
memdrill数据是Spring Roo管理的项目。这里没有web组件。我只是:

persistence setup --provider HIBERNATE --database HYPERSONIC_PERSISTENT
并添加了一些实体。例如:

@RooJavaBean
@RooToString
@RooEntity
public class Item {

    @NotNull
    @Column(unique = true)
    @Size(min = 1, max = 200)
    private String itemId;

    @NotNull
    @Lob
    @OneToOne(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY)
    private LobString content;
}

@RooJavaBean
@RooEntity
public class LobString {

    @Lob
    @Basic(fetch=FetchType.LAZY)
    private String data;

    public LobString() {
        super();
    }

    public LobString(String data) {
        this.data = data;
    }
}
这不要紧,但为了记录在案,我使用的是Roo1.1.4。本次讨论中可能不需要applicationContext.xml,但在这里它仍然存在(由Roo生成后未被触及):

因此,当我尝试访问延迟加载的数据以填充LobString POJO时,没有正在进行的会话,它会崩溃

我能找到的最接近LobString访问代码(例如,item.getContent().getId())的地方(在我的代码中,即不是我所依赖的库中)是类似于推入findAllItems()或创建这样的新方法来说明这一点:

public static List<Item> findAllItemsWithRefs() {
    List<Item> items = entityManager().createQuery("SELECT o FROM Item o", Item.class).getResultList();
    for(Item item : items) {
        System.out.println("item.getContent().getId() = " + item.getContent().getId());
    }
    return items;
}
我得到:

persist - OK
2014-07-05 16:17:35,707 [main] DEBUG org.hibernate.SQL - select item0_.id as id1_, item0_.content as content1_, item0_.item_id as item2_1_, item0_.version as version1_ from item item0_
2014-07-05 16:17:35,711 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [1] as column [id1_]
2014-07-05 16:17:35,713 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [1] as column [content1_]
2014-07-05 16:17:35,713 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [abc123] as column [item2_1_]
2014-07-05 16:17:35,713 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [0] as column [version1_]
i.getId() = 1
i.getItemId() = abc123
2014-07-05 16:17:35,717 [main] ERROR org.hibernate.LazyInitializationException - could not initialize proxy - no Session
因此,正如“find as column[content1_uz]一行所示,我至少拥有表中包含LobString数据的行的外键……但是如果不获得LazyInitializationException,我就无法访问该id。如果我能够获得LobString,也许我可以通过id获取它……但是I.getContent()和I.getContent().getId()给出异常。外键应与LobString表的主键id匹配,即i.getContent().getId()…但似乎无法从i…访问外键,如日志所示,它实际上是从db中获取的

在任何情况下,即使我得到了外键…必须保持LobString.find(id)或类似的方式不是一个好的解决方案。Hibernate应该填充您的对象图

Edit2:

在这次编辑中需要指出的两点。执行过程包括以下几点:
org.springframework.orm.jpa.SharedEntityManagerCreator.DeferredQueryInvocationHandler.invoke(Object,Method,Object[])

首先,如果使用“getResultList”,EntityManager将被关闭。我将假设EntityManager是一个JPA构造,它映射到Hibernate的会话,而不进行详细说明

第二…如果我在调试时深入研究,我可以看到应该延迟加载的数据“这是项的内容”…因此我实际上在内存中加载了该数据…1)因为它是延迟的,所以它不应该2)即使它在那里,我也无法访问它,因为我得到了LazyInitializationException

调试时,我可以看到数据加载在以下两个地方:

1) 我的主方法(请参见上文:主方法中的Item i=items.get(0))
com.memdrill.prototype.datause.Main.Main(字符串[])

i->content->handler->target->data:“这是项目的内容”

2) 在关闭会话的方法中:
org.springframework.orm.jpa.SharedEntityManagerCreator.DeferredQueryInvocationHandler.invoke(对象、方法、对象[])

retVal->elementData[0]->content->handler->target->data:“这是项的内容”

懒散加载的数据就这么多了……我做错了什么

我似乎也有LobString的规范要延迟加载。但如果是这样的话,而且我的内存中确实有内容……为什么我不能访问它

Edit3:

看起来Edit2中的行为(在内存中延迟加载数据)只有在调试时才会发生,如果我在调试模式中停留足够长的时间

因此,基本上,如果我在调试模式下运行,在断点处一直点击“播放”“播放”“播放”,我会得到LazyInitializationException…但是如果我在调试模式下停留足够长的时间,没有LazyInitializationException,我会得到数据并打印到标准输出

有什么想法吗

Edit4:

多亏了,我现在能够使用以下工具急切地获取所有LobString:

    EntityManager em = Item.entityManager();
    List<Item> items = em.createQuery("SELECT o FROM Item o JOIN FETCH o.content", Item.class).getResultList();
这几乎就是我想要的。我只想要LobString的ID。我的想法是这将是一个REST调用,我只想返回项目“基本”数据和LobString的ID,它们可以用于单独的请求


你知道什么样的JPQL查询可以实现这一点吗?(任何有助于理解引擎盖下发生的事情的评论都将不胜感激)-谢谢

好的,所以答案毕竟是开着的:

最后,我在LobString\u Roo\u Entity.aj中输入了
private Long id
,并添加了
@Access(AccessType.PROPERTY)
注释:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
@Access(AccessType.PROPERTY)
private Long id;
现在,使用Item.findAllItems()如下所示:

    Item item = new Item();
    item.setItemId("abc123");
    item.setContent(new LobString("this is the lob data"));

    item.persist();

    System.out.println("persist - OK");

    List<Item> items = Item.findAllItems();

    Item i = items.get(0);

    System.out.println("i.getId() = " + i.getId());
    System.out.println("i.getItemId() = " + i.getItemId());
    //      System.out.println("i.getContent() = " + i.getContent());
    System.out.println("i.getContent().getId() = " + i.getContent().getId());
    System.out.println("i.getContent().getData() = " + i.getContent().getData());
如果注释掉的行未注释,则在打印
i.getContent().getId()=1
之前会发生LazyInitializationException

这是我一直在寻找的行为……不幸的是……我真的不明白发生了什么。如果你认为你能解释一下发生了什么,请解释一下

谢谢

Edit1:


注:我不认为这是一个答案,因为它只回答了这个特殊的情况。我需要弄清楚如何恰当地划定事务。我猜想我可以手动实例化交易并在代码中有交叉切关。我想知道当前的配置。限制T的是什么?Transaction to findAllItems()?如何配置它?

要解决这个问题,可以在非静态方法上使用
@Transactional
注释

例如:

@RooJavaBean
@RooToString
@RooEntity
public class Item {

    @NotNull
    @Column(unique = true)
    @Size(min = 1, max = 200)
    private String itemId;

    @NotNull
    @Lob
    @OneToOne(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY)
    private LobString content;

    @Transactional(readOnly=true)
    LobString loadContent(){
       getContent().getId();
       return getContent();
    }
}
然后,使用
loadContent()
方法获取
LobString

这是因为当您调用
i.getContent()
时,用于加载数据的数据库连接已经关闭

使用带注释的方法
@transaction a
persist - OK
2014-07-05 16:17:35,707 [main] DEBUG org.hibernate.SQL - select item0_.id as id1_, item0_.content as content1_, item0_.item_id as item2_1_, item0_.version as version1_ from item item0_
2014-07-05 16:17:35,711 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [1] as column [id1_]
2014-07-05 16:17:35,713 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [1] as column [content1_]
2014-07-05 16:17:35,713 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [abc123] as column [item2_1_]
2014-07-05 16:17:35,713 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [0] as column [version1_]
i.getId() = 1
i.getItemId() = abc123
2014-07-05 16:17:35,717 [main] ERROR org.hibernate.LazyInitializationException - could not initialize proxy - no Session
        // Invoke method on actual Query object.
        try {
            Object retVal = method.invoke(this.target, args);
            return (retVal == this.target ? proxy : retVal);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
        finally {
            if (method.getName().equals("getResultList") || method.getName().equals("getSingleResult") ||
                    method.getName().equals("executeUpdate")) {
                EntityManagerFactoryUtils.closeEntityManager(this.em);
            }
        }
    EntityManager em = Item.entityManager();
    List<Item> items = em.createQuery("SELECT o FROM Item o JOIN FETCH o.content", Item.class).getResultList();
2014-07-06 21:44:56,862 [main] INFO  org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Building JPA container EntityManagerFactory for persistence unit 'persistenceUnit'
in LobString default constructor
in LobString (String data) constructor
2014-07-06 21:44:57,891 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [com.memdrill.data.entity.Item.persist]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2014-07-06 21:44:57,944 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@779d9c0d] for JPA transaction
2014-07-06 21:44:57,948 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Not exposing JPA transaction [org.hibernate.ejb.EntityManagerImpl@779d9c0d] as JDBC transaction because JpaDialect [org.springframework.orm.jpa.DefaultJpaDialect@d7e60a1] does not support JDBC Connection retrieval
2014-07-06 21:44:57,999 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction commit
2014-07-06 21:44:58,000 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@779d9c0d]
2014-07-06 21:44:58,002 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@779d9c0d] after transaction
2014-07-06 21:44:58,002 [main] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
persist - OK - in Main of memdrill-data not data-use
2014-07-06 21:44:58,008 [main] DEBUG org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler - Creating new EntityManager for shared EntityManager invocation
in LobString default constructor
2014-07-06 21:44:58,133 [main] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
i.getId() = 1
i.getItemId() = abc123
i.getContent() = com.memdrill.data.util.LobString@6fe30af
i.getContent().getId() = 1
i.getContent().getData() = this is the content of the item
2014-07-06 21:44:58,134 [main] INFO  org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'persistenceUnit'
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
@Access(AccessType.PROPERTY)
private Long id;
    Item item = new Item();
    item.setItemId("abc123");
    item.setContent(new LobString("this is the lob data"));

    item.persist();

    System.out.println("persist - OK");

    List<Item> items = Item.findAllItems();

    Item i = items.get(0);

    System.out.println("i.getId() = " + i.getId());
    System.out.println("i.getItemId() = " + i.getItemId());
    //      System.out.println("i.getContent() = " + i.getContent());
    System.out.println("i.getContent().getId() = " + i.getContent().getId());
    System.out.println("i.getContent().getData() = " + i.getContent().getData());
i.getId() = 1
i.getItemId() = abc123
i.getContent().getId() = 1
2014-07-06 22:32:51,309 [main] ERROR org.hibernate.LazyInitializationException - could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
@RooJavaBean
@RooToString
@RooEntity
public class Item {

    @NotNull
    @Column(unique = true)
    @Size(min = 1, max = 200)
    private String itemId;

    @NotNull
    @Lob
    @OneToOne(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY)
    private LobString content;

    @Transactional(readOnly=true)
    LobString loadContent(){
       getContent().getId();
       return getContent();
    }
}
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <!-- NB: do use 1.3 or 1.3.x due to MASPECTJ-90 - wait for 1.4 -->
<!--                 <version>1.5</version> -->
                <version>1.2</version>


                <dependencies>
                    <!-- NB: You must use Maven 2.0.9 or above or these are ignored (see MNG-2972) -->
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <outxml>true</outxml>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                    <complianceLevel>1.6</complianceLevel>
                    <source>1.6</source>
                    <target>1.6</target>
<!--                     <complianceLevel>${java.version}</complianceLevel> -->
<!--                    <source>${java.version}</source> -->
<!--                    <target>${java.version}</target> -->
                </configuration>
            </plugin>
@Transactional(readOnly=true)
    public List<Item> findAllItemsWithContentId() {
        List<Item> items = entityManager().createQuery(
                "SELECT o FROM Item o", Item.class)
                .getResultList();

        for(Item item: items) {
            System.out.println("about to item.getContent().getId()");
            System.out.println(item.getContent().getId());
        }
        return items;
    }
List<Item> items = new Item().findAllItemsWithContentId();
Item i = items.get(0);

System.out.println("i.getId() = " + i.getId());
System.out.println("i.getItemId() = " + i.getItemId());
System.out.println("i.getContent() = " + i.getContent());
System.out.println("i.getContent().getId() = " + i.getContent().getId());
System.out.println("i.getContent().getData() = " + i.getContent().getData());