2011-12-14 2 views
1

JPA провайдер EclipseLink 2.3 КАК GlassFish 3.1.1 В12 Двоичного протокол для удаленного вызова гессенскомПочему JPA FetchType.LAZY не работает?

стороны сервера EJB + JPA стороны клиента Plain Swing.

JPA отображение

@Entity 
@Table(name = "FATHER", catalog = "CAT", schema = "dbo") 
public class Father implements Serializable { 

    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(generator = "FATHERUID", strategy = GenerationType.TABLE) 
    @TableGenerator(name = "FATHERUID", table = "FAMILY_UID", catalog = "LSDB", schema = "dbo", pkColumnName = "PRIM", pkColumnValue = "father_uid", valueColumnName = "UID", allocationSize = 1, initialValue = 0) 
    private Long id; 

    @OneToOne(mappedBy = "father", fetch = FetchType.LAZY) 
    private Mother mother; 

    @OneToMany(mappedBy = "father", fetch = FetchType.LAZY) 
    private List<Friend> friendList; 

} 


@Entity 
@Table(name = "FRIEND", catalog = "CAT", schema = "dbo") 
@NamedQueries({ 
    @NamedQuery(name = "Friend.findAll", query = "SELECT f FROM Friend f")}) 
public class Friend implements Serializable { 

    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(generator = "FRIENDUID", strategy = GenerationType.TABLE) 
    @TableGenerator(name = "FRIENDUID", table = "FAMILY_UID", catalog = "LSDB", schema = "dbo", pkColumnName = "PRIM", pkColumnValue = "friend_uid", valueColumnName = "UID", allocationSize = 1, initialValue = 0) 
    private Long id; 

    @JoinColumn(name = "FATHERID", referencedColumnName = "ID") 
    @ManyToOne(optional = false,fetch= FetchType.LAZY) 
    private Father father; 

} 

EJB Метод

public Father findFather(long id) { 

     Father fath = em.find(Father.class, id); 

     PersistenceUnitUtil util = em.getEntityManagerFactory().getPersistenceUnitUtil(); 

     System.out.println("mother isloaded="+util.isLoaded(fath,"mother")); 
     System.out.println("friendList isloaded="+util.isLoaded(fath,"friendList")); 

     return fath; 
    } 

стороны клиента вызова через Гесс

public void findFather() { 

     try { 

     IManager manager = ProxyHelper.getStub(); 
     //find by father id 
     Father father = manager.findFather(3500L); 

     System.out.println("Father=" + father); 
     System.out.println("father's friends=" + father.getFriendList()); 
     System.out.println("mother=" + father.getMother()); 

    } catch (MalformedURLException ex) { 

    } 

} 

все работает нормально, но при просмотре журнала сервера и связанных сторонах Отца я обнаружил , что поля с нотами LazyLoaded заполнены из базы данных.

Server Log

FINEST: Begin deploying Persistence Unit test; session file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test; state Predeployed; factoryCount 1 
INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver. 
FINEST: property=eclipselink.target-server; value=SunAS9; translated value=org.eclipse.persistence.platform.server.sunas.SunAS9ServerPlatform 
FINEST: property=eclipselink.logging.level; value=FINEST; translated value=FINEST 
FINEST: property=eclipselink.logging.parameters; value=true 
FINEST: property=eclipselink.logging.level; value=FINEST; translated value=FINEST 
FINEST: property=eclipselink.logging.parameters; value=true 
FINEST: property=eclipselink.cache.shared.default; value=false; translated value=false 
INFO: EclipseLink, version: Eclipse Persistence Services - 2.3.2.v20111125-r10461 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.Oracle11Platform, regular expression: (?i)oracle.*11 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.Oracle10Platform, regular expression: (?i)oracle.*10 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.Oracle9Platform, regular expression: (?i)oracle.*9 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.OraclePlatform, regular expression: (?i)oracle.* 
FINEST: Database platform: org.eclipse.persistence.platform.database.SQLAnywherePlatform, regular expression: SQL\ Anywhere.* 
FINEST: Database platform: org.eclipse.persistence.platform.database.SybasePlatform, regular expression: (?i)(sybase.*)|(adaptive\ server\ enterprise.*)|(SQL\ Server.*) 
FINEST: Database platform: org.eclipse.persistence.platform.database.SQLServerPlatform, regular expression: (?i)microsoft.* 
FINE: Detected database platform: org.eclipse.persistence.platform.database.SQLServerPlatform 
CONFIG: connecting(DatabaseLogin(
    platform=>DatabasePlatform 
    user name=> "" 
    connector=>JNDIConnector datasource name=>null 
)) 
CONFIG: Connected: jdbc:jtds:sqlserver: 
    User: user 
    Database: Microsoft SQL Server Version: 10.50.1600 
    Driver: jTDS Type 4 JDBC Driver for MS SQL Server and Sybase Version: 1.2.5 
FINEST: Connection acquired from connection pool [read]. 
FINEST: Connection released to connection pool [read]. 
CONFIG: connecting(DatabaseLogin(
    platform=>SQLServerPlatform 
    user name=> "" 
    connector=>JNDIConnector datasource name=>null 
)) 
CONFIG: Connected: jdbc:jtds:sqlserver: 
    User: user 
    Database: Microsoft SQL Server Version: 10.50.1600 
    Driver: jTDS Type 4 JDBC Driver for MS SQL Server and Sybase Version: 1.2.5 
FINEST: sequencing connected, state is Preallocation_Transaction_NoAccessor_State 
FINEST: sequence child_uid: preallocation size 1 
FINEST: sequence friend_uid: preallocation size 1 
FINEST: sequence father_uid: preallocation size 1 
FINEST: sequence mother_uid: preallocation size 1 
INFO: file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test login successful 
WARNING: Multiple [2] JMX MBeanServer instances exist, we will use the server at index [0] : [[email protected]]. 
FINER: JMX MBeanServer instance found: [[email protected]], # of beans: [21], domain: [DefaultDomain] at index: [0]. 
WARNING: JMX MBeanServer in use: [[email protected]] from index [0] 
FINER: JMX MBeanServer instance found: [[email protected]], # of beans: [24], domain: [DefaultDomain] at index: [1]. 
WARNING: JMX MBeanServer in use: [[email protected]] from index [1] 
FINEST: Registered MBean: org.eclipse.persistence.services.mbean.MBeanDevelopmentServices[TopLink:Name=Development-file_/C_/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test,Type=Configuration] on server [email protected] 
FINEST: Registered MBean: org.eclipse.persistence.services.glassfish.MBeanGlassfishRuntimeServices[TopLink:Name=Session(file_/C_/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test)] on server [email protected] 
FINEST: EclipseLink JMX Runtime Services is referencing the [Platform ConversionManager] ClassLoader at: [WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)] 
FINEST: The applicationName for the MBean attached to session [file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test] is [unknown] 
FINEST: The moduleName for the MBean attached to session [file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test] is [unknown] 
FINER: Canonical Metamodel class [org.dima.model.Child_] not found during initialization. 
FINER: Canonical Metamodel class [org.dima.model.Friend_] not found during initialization. 
FINER: Canonical Metamodel class [org.dima.model.Father_] not found during initialization. 
FINER: Canonical Metamodel class [org.dima.model.Mother_] not found during initialization. 
FINEST: End deploying Persistence Unit test; session file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test; state Deployed; factoryCount 1 
FINER: client acquired: 50658177 
FINER: TX binding to tx mgr, status=STATUS_ACTIVE 
FINER: acquire unit of work: 1008456627 
FINEST: Execute query ReadObjectQuery(name="readObject" referenceClass=Father sql="SELECT ID, NAME, SURNAME FROM LSDB.dbo.FATHER WHERE (ID = ?)") 
FINEST: Connection acquired from connection pool [read]. 
FINEST: reconnecting to external connection pool 
FINE: SELECT ID, NAME, SURNAME FROM LSDB.dbo.FATHER WHERE (ID = ?) 
    bind => [3500] 
FINEST: Connection released to connection pool [read]. 
INFO: mother isloaded=false 
INFO: friendList isloaded=false 
FINER: TX beforeCompletion callback, status=STATUS_ACTIVE 
FINER: begin unit of work commit 
FINER: TX afterCompletion callback, status=COMMITTED 
FINER: end unit of work commit 
FINER: release unit of work 
FINER: client released 
FINEST: Execute query ReadAllQuery(name="file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test" referenceClass=Friend) 
FINEST: Connection acquired from connection pool [read]. 
FINEST: reconnecting to external connection pool 
**FINE: SELECT ID, NAME, SURNAME, FATHERID FROM LSDB.dbo.FRIEND WHERE (FATHERID = ?) 
    bind => [3500]** 
FINEST: Connection released to connection pool [read]. 
FINEST: Register the existing object org.dima.model.Friend[ id=17496 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17497 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17498 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17499 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17500 ] 

Почему JPA провайдер выполняет эту SELECT, ID, имя, фамилия, FATHERID ОТ LSDB.dbo.FRIEND ГДЕ (FATHERID =?) связываются => [3500]

Любая идея?

ответ

2

Lazy fetch type работает. Lazy отношения позволяют отложить выборку объектов, на которые ссылаются, до тех пор, пока они не будут впервые доступны, что, кажется, происходит, когда вы вызываете father.getFriendList(). Если это не сработало, этот вызов ничего не сделает, и отношения будут получены сразу после того, как отец был зачитан.

EclipseLink позволяет получить доступ к ленивым отношениям, пока соединение все еще доступно, как описано здесь: http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg05258.html Если вы сериализуете вы получите исключение, поскольку контекст для чтения в отношениях не будет доступен.

Если вы хотите, чтобы исключение было выбрано вместо этого, когда вы обращаетесь к ленивым отношениям на отдельном, но не сериализованном объекте, напишите запрос расширения в EclipseLink.

+1

Разве это (неявный) вызов метода toString() списка, который запускает ленивую загрузку? –

+2

Кроме того, я нахожу это поведение (от ленивой загрузки после совершения транзакции) сомнительным: если в транзакции есть уровень изоляции READ_COMMITTED (или более строгий), lazy-load list после завершения транзакции позволяет видеть детей, которых не было когда транзакция выполнялась, и не показывает дочерние элементы, существовавшие при выполнении транзакции, но с тех пор были удалены. Вы теряете I и C в ACID. –

+0

Lazy loading работает отлично, но при первом доступе к серверу объекта отцов выполняется sql select на Friends Friends. как остановить выполнение sql на дочернем объекте «SELECT ID, NAME, SURNAME, FATHERID FROM LSDB.dbo.FRIEND WHERE (FATHERID =?) bind => [3500]" – dimitri

5

Lazy loading выполняется только для отношения xToMany в среде Java SE по умолчанию (поскольку EclipseLink может использовать IndirectList, где используются коллекции). Если вам нужна ленивая загрузка xToOne, вам нужно использовать классное сотканье.

+0

Вы король лаборатории. Я люблю тебя. – Alex

0

EAGER стратегия является требованием на поставщик сохранения выполнения, что это значение должно быть охотно извлекается. Стратегия LAZY - это Подсказка времени выполнения поставщика.

Нашел этот ответ здесь. JPA fetchType.Lazy is not working

Еще одна вещь: JPA использует ткачество для достижения этого.wiki-eclipse

Смежные вопросы