jpa的初步入门

   网上关于jpa的例子很多,今天还是来讲入门,主要在例子中讲解一下各个jpa实现的对比,首先来一个hibernate对于jpa的实现,首先是jpa的配置文件
META-INF下的persist.xml,目前jpa规范中必须是放在这个目录下。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence   
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
    <persistence-unit name="jpa"
        transaction-type="RESOURCE_LOCAL">
       <properties>
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        </properties>
    </persistence-unit>
</persistence>

测试代码如下
package org.ww;

import javax.persistence.Persistence;

public class JpaTest {
 public static void main(String[] args) {
  System.out.println(Persistence.createEntityManagerFactory("jpa"));
 }
}


这样虽然会报错,没有配置mysql的driverclass,但是会输出 org.hibernate.ejb.EntityManagerFactoryImpl@16e481a
在这里我们是没有配置provider的,
在persist.xml中provider不是必须配置的,但是如果你的项目中出现多个jpa实现,这时候你想使用哪个provider就必须配置相应的provider,在这里我没有配置provider,但它使用了hibernate,
jpa是PersistenceProviderResolverHolder的CachingPersistenceProviderResolver
private void loadResolverClasses(ClassLoader cl) {
    synchronized ( resolverClasses ) {
     try {
      Enumeration<URL> resources = cl.getResources( "META-INF/services/" + PersistenceProvider.class.getName() );
      Set<String> names = new HashSet<String>();
      while ( resources.hasMoreElements() ) {
       URL url = resources.nextElement();
       InputStream is = url.openStream();
       try {
        names.addAll( providerNamesFromReader( new BufferedReader( new InputStreamReader( is ) ) ) );
       }
       finally {
        is.close();
       }
      }
      for ( String s : names ) {
       @SuppressWarnings( "unchecked" )
       Class<? extends PersistenceProvider> providerClass = (Class<? extends PersistenceProvider>) cl.loadClass( s );
       WeakReference<Class<? extends PersistenceProvider>> reference
         = new WeakReference<Class<? extends PersistenceProvider>>(providerClass);
       //keep Hibernate atop
       if ( s.endsWith( "HibernatePersistence" ) && resolverClasses.size() > 0 ) {
        WeakReference<Class<? extends PersistenceProvider>> movedReference = resolverClasses.get( 0 );
        resolverClasses.add( 0, reference );
        resolverClasses.add( movedReference );
       }
       else {
        resolverClasses.add( reference );
       }
      }
     }
     catch ( IOException e ) {
      throw new PersistenceException( e );
     }
     catch ( ClassNotFoundException e ) {
      throw new PersistenceException( e );
     }
    }
   }

在这里我们看到是通过查找meta-inf/services/javax.persistence.spi.PersistenceProvider中的内容来使用相应的provider,在hibernate-entitymanager中看到了
            
查找的是这个provider,在这个provider里面会读取配置persist.xml然后生成entitymanagerFactory
public static EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) {
  EntityManagerFactory emf = null;
  List<PersistenceProvider> providers = getProviders();
  for ( PersistenceProvider provider : providers ) {
   emf = provider.createEntityManagerFactory( persistenceUnitName, properties );
   if ( emf != null ) {
    break;
   }
  }
  if ( emf == null ) {
   throw new PersistenceException( "No Persistence provider for EntityManager named " + persistenceUnitName );
  }
  return emf;
 }


这里使用的org.hibernate.ejb.hibernatePersitence作为provider,在createEntityMangeFactory中使用的EJB3Configuration来创建entitymanageFactory,其中有一段代码如下
 if ( metadata.getProvider() == null || IMPLEMENTATION_NAME.equalsIgnoreCase(
       metadata.getProvider()
     ) ) {
      //correct provider

      //lazy load the scanner to avoid unnecessary IOExceptions
      Scanner scanner = null;
      URL jarURL = null;
      if ( metadata.getName() == null ) {
       scanner = buildScanner( metadata.getProps(), integration );
       jarURL = JarVisitorFactory.getJarURLFromURLEntry( url, "/META-INF/persistence.xml" );
       metadata.setName( scanner.getUnqualifiedJarName(jarURL) );
      }
      if ( persistenceUnitName == null && xmls.hasMoreElements() ) {
       throw new PersistenceException( "No name provided and several persistence units found" );
      }
      else if ( persistenceUnitName == null || metadata.getName().equals( persistenceUnitName ) ) {
       if (scanner == null) {
        scanner = buildScanner( metadata.getProps(), integration );
        jarURL = JarVisitorFactory.getJarURLFromURLEntry( url, "/META-INF/persistence.xml" );
       }
       //scan main JAR
       ScanningContext mainJarScanCtx = new ScanningContext()
         .scanner( scanner )
         .url( jarURL )
         .explicitMappingFiles( metadata.getMappingFiles() )
         .searchOrm( true );
       setDetectedArtifactsOnScanningContext( mainJarScanCtx, metadata.getProps(), integration,
                    metadata.getExcludeUnlistedClasses() );
       addMetadataFromScan( mainJarScanCtx, metadata );

       ScanningContext otherJarScanCtx = new ScanningContext()
         .scanner( scanner )
         .explicitMappingFiles( metadata.getMappingFiles() )
         .searchOrm( true );
       setDetectedArtifactsOnScanningContext( otherJarScanCtx, metadata.getProps(), integration,
                    false );
       for ( String jarFile : metadata.getJarFiles() ) {
        otherJarScanCtx.url( JarVisitorFactory.getURLFromPath( jarFile ) );
        addMetadataFromScan( otherJarScanCtx, metadata );
       }
       return configure( metadata, integration );
      }
     }
    }
   }
   return null;



在这里,如果xml的provider为空,或者provider不为空但是与自己本身的名字相等则创建entitymanageFactory,否则返回空。只要entityManageFactory创建完成,配置读取就完毕了。
为此,我将多个jpa的实现集成的项目中,EclipseLink,openJpa。如果我的persist.xml中的provider没有写,则默认创建hibernate的provider,然后程序结束,如果xml中写了EclipseLink的provider,则会先执行hibernate,然后执行Eclipselink的provider,然后创建成功。如果配置openjpa的则openjpa的provider是最后一个执行的,这里执行的顺序不固定,在不同的机器上可能不同,但是即使配置了多个jpa,也可以指定想要的jpa实现,唯一的就是实现的效率的问题。也可以不同的persistunit指定不同的jpa实现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值