jpa jdbc jndi_没有J2EE容器的JNDI和JPA

jpa jdbc jndi

我们希望通过尽可能简单的设置来测试一些JPA代码。 计划仅使用Java和Maven,不使用应用程序服务器或其他J2EE容器。

我们的JPA配置需要两件事才能成功运行:

  • 数据库来存储数据,
  • JNDI访问数据库。

这篇文章分为两个部分。 第一部分显示了如何在测试中使用独立的JNDI和嵌入式内存数据库。 其余各章说明了该解决方案的工作方式。

所有使用的代码都可以在Github上找到 。 如果您对解决方案感兴趣,但不想阅读说明,请从Github下载项目并仅阅读第一章。

JPA测试

本章说明如何在测试中使用我们的代码来启用独立的JNDI和嵌入式内存数据库。 本文的其余部分将说明该解决方案的工作方式和原因。

该解决方案具有三个“ API”类:

  • JNDIUtil – JNDI初始化,清理和一些便捷方法,
  • InMemoryDBUtil –数据库和数据源的创建/删除,
  • AbstractTestCase –在第一次测试之前清理数据库,在每次测试之前清理JNDI。

我们使用Liquibase维护数据库结构。 如果您不想使用Liquibase,则必须自定义InMemoryDBUtil类。 调整方法createDatabaseStructure以执行所需的操作。

Liquibase将所有需要的数据库更改的列表保存在名为changelog的文件中。 除非另行配置,否则每个更改仅运行一次。 即使将更改日志文件多次应用于同一数据库。

用法

AbstractTestCase扩展的任何测试用例都将:

  • 在第一次测试之前删除数据库,
  • 在每次测试之前安装独立的JNDI或删除其中存储的所有数据,
  • 每次测试之前,请对数据库运行Liquibase changelog。

JPA测试用例必须扩展AbstractTestCase并重写getInitialChangeLog方法。 该方法应返回changelog文件位置。

public class DemoJPATest extends AbstractTestCase {private static final String CHANGELOG_LOCATION = "src/test/java/org/meri/jpa/simplest/db.changelog.xml";private static EntityManagerFactory factory;public DemoJPATest() {}@Overrideprotected String getInitialChangeLog() {return CHANGELOG_LOCATION;}@Test@SuppressWarnings("unchecked")public void testJPA() {EntityManager em = factory.createEntityManager();Query query = em.createQuery("SELECT x FROM Person x");List<Person> allUsers = query.getResultList();em.close();assertFalse(allUsers.isEmpty());}@BeforeClasspublic static void createFactory() {factory = Persistence.createEntityManagerFactory("Simplest");}@AfterClasspublic static void closeFactory() {factory.close();}}

注意:在每次测试之前删除数据库会更清洁。 但是,删除并重新创建数据库结构是昂贵的操作。 这会使测试用例放慢太多。 仅在上课之前这样做似乎是一种合理的折衷。

虽然数据库仅删除一次,但更改日志在每次测试之前运行。 看起来似乎很浪费,但是此解决方案具有一些优势。 首先, getInitialChangeLog方法不必是静态的,并且可以在每个测试中覆盖。 其次,配置为“ runAlways”的更改将在每次测试之前运行,因此可能包含一些廉价的清理或其他初始化操作。

日本国家发展研究院

本章说明什么是JNDI,如何使用它以及如何配置它。 如果您对理论不感兴趣,请跳至下一章。 在此创建独立的JNDI。

基本用法

JNDI允许客户端通过名称存储和查找数据和对象。 数据存储通过Context接口的实现来访问。

以下代码显示了如何在JNDI中存储数据:

Context ctx = new InitialContext();
ctx.bind("jndiName", "value");
ctx.close();

第二段代码显示了如何在JNDI中查找内容:

Context ctx = new InitialContext();
Object result = ctx.lookup("jndiName");
ctx.close();

尝试在没有J2EE容器的情况下运行以上代码,您会得到一个错误:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initialat javax.naming.spi.NamingManager.getInitialContext(Unknown Source)at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)at javax.naming.InitialContext.bind(Unknown Source)at org.meri.jpa.JNDITestCase.test(JNDITestCase.java:16)at ...

该代码不起作用,因为InitialContext类不是真实的数据存储。 InitialContext类只能找到Context接口的另一个实例,并将所有工作委托给它。 它既无法存储数据也无法找到它们。

上下文工厂

真正的上下文,即完成所有工作并能够存储/查找数据的上下文,必须由上下文工厂创建。 本节说明如何创建上下文工厂以及如何配置InitialContext以使用它。

每个上下文工厂必须实现InitialContextFactory接口,并且必须具有无参数构造函数:

package org.meri.jpa.jndi;public class MyContextFactory implements InitialContextFactory {@Overridepublic Context getInitialContext(Hashtable environment) throws NamingException {return new MyContext();}}

我们的工厂返回一个简单的上下文,称为MyContext 。 其lookup方法始终返回字符串“存储的值”:

class MyContext implements Context {@Overridepublic Object lookup(Name name) throws NamingException {return "stored value";}@Overridepublic Object lookup(String name) throws NamingException {return "stored value";}.. the rest ...
}

JNDI配置在哈希表中的类之间传递。 键始终包含属性名称,而值包含属性值。 由于初始上下文构造函数InitialContext()没有参数,因此假定为空哈希表。 该类还具有一个替代构造函数,该构造函数将配置属性哈希表作为参数。

使用属性"java.naming.factory.initial"来指定上下文工厂类名称。 该属性在Context.INITIAL_CONTEXT_FACTORY常量中定义。

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "className");Context ctx = new InitialContext(environnement);

下一步测试配置MyContextFactory并检查创建的初始上下文是否返回“存储值”,无论如何:

@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testDummyContext() throws NamingException {Hashtable environnement = new Hashtable();environnement.put(Context.INITIAL_CONTEXT_FACTORY, "org.meri.jpa.jndi.MyContextFactory");Context ctx = new InitialContext(environnement);Object value = ctx.lookup("jndiName");ctx.close();assertEquals("stored value", value);
}

当然,仅当您可以将具有自定义属性的哈希表提供给初始上下文构造函数时,此方法才有效。 这通常是不可能的。 大多数库使用开头所示的无参数构造函数。 他们假设初始上下文类具有可用的默认上下文工厂,并且无参数构造函数将使用该工厂。

命名经理

初始上下文使用NamingManager创建真实上下文。 命名管理器具有静态方法getInitialContext(Hashtable env) ,该方法返回上下文的实例。 参数env包含用于构建上下文的配置属性。

默认情况下,命名管理器读取Context.INITIAL_CONTEXT_FACTORYenv哈希表,并创建指定的初始上下文工厂的实例。 然后,工厂方法将创建一个新的上下文实例。 如果未设置该属性,则命名管理器将引发异常。

可以自定义命名管理员的行为。 NamingManager类具有方法setInitialContextFactoryBuilder 。 如果设置了初始上下文工厂构建器,则命名管理器将使用它来创建上下文工厂。

您只能使用此方法一次。 已安装的上下文工厂生成器无法更改。

try {MyContextFactoryBuilder builder = new MyContextFactoryBuilder();NamingManager.setInitialContextFactoryBuilder(builder);
} catch (NamingException e) {// handle exception
}

初始上下文工厂构建器必须实现InitialContextFactoryBuilder接口。 界面很简单。 它只有一个方法InitialContextFactory createInitialContextFactory(Hashtable env)

摘要

简而言之,初始上下文将实际的上下文初始化委托给命名管理器,命名管理器将其委托给上下文工厂。 上下文工厂由初始上下文工厂构建器的实例创建。


独立JNDI

我们将创建并安装独立的JNDI实现。 我们的独立JNDI实现的入口点是JNDIUtil类。

在没有应用程序服务器的情况下启用JNDI需要三件事:

  • ContextInitialContextFactory接口的实现,
  • InitialContextFactoryBuilder接口的实现,
  • 初始上下文工厂构建器的安装以及清除所有存储数据的能力。

上下文和工厂

我们从osjava项目中获取了SimpleJNDI实现,并对其进行了修改以更好地满足我们的需求。 该项目使用了新的BSD许可证 。

将SimpleJNDI maven依赖项添加到pom.xml中:

simple-jndisimple-jndi0.11.4.1

SimpleJNDI带有一个MemoryContext上下文,该上下文专门存在于内存中。 它几乎不需要任何配置,并且其状态永远不会保存下来。 它几乎满足了我们的需求,除了两件事:

  • 它的close()方法删除所有存储的数据,
  • 每个实例默认使用其自己的存储。

大多数库都假定close方法优化了资源。 他们倾向于在每次加载或存储数据时调用它。 如果close方法在存储完所有数据后立即删除它们,则上下文将无用。 我们必须扩展MemoryContext类并重写close方法:

@SuppressWarnings({"rawtypes"}) 
public class CloseSafeMemoryContext extends MemoryContext {public CloseSafeMemoryContext(Hashtable env) {super(env);}@Overridepublic void close() throws NamingException {// Original context lost all data on close();// That made it unusable for my tests. }}

按照约定,建造者/工厂系统会为每次使用创建新的上下文实例。 如果它们不共享数据,则不能使用JNDI在不同库之间传输数据。

幸运的是,这个问题也很容易解决。 如果环境哈希表包含值为"true"属性"org.osjava.sj.jndi.shared" "true" ,则创建的内存上下文将使用公共静态存储。 因此,我们的初始上下文工厂将创建CloseSafeMemoryContext实例,并将其配置为使用公共存储:

public class CloseSafeMemoryContextFactory implements InitialContextFactory {private static final String SHARE_DATA_PROPERTY = "org.osjava.sj.jndi.shared";public Context getInitialContext(Hashtable environment) throws NamingException {// clone the environnementHashtable sharingEnv = (Hashtable) environment.clone();// all instances will share stored dataif (!sharingEnv.containsKey(SHARE_DATA_PROPERTY)) {sharingEnv.put(SHARE_DATA_PROPERTY, "true");}return new CloseSafeMemoryContext(sharingEnv);;}}

初始上下文工厂生成器

我们的构建器的行为几乎与原始命名管理器实现相同。 如果传入环境中存在属性Context.INITIAL_CONTEXT_FACTORY ,则将创建指定的工厂。

但是,如果缺少此属性,则构建器将创建CloseSafeMemoryContextFactory的实例。 原始的命名管理器将引发异常。

我们对InitialContextFactoryBuilder接口的实现:

public InitialContextFactory createInitialContextFactory(Hashtable env) throws NamingException {String requestedFactory = null;if (env!=null) {requestedFactory = (String) env.get(Context.INITIAL_CONTEXT_FACTORY);}if (requestedFactory != null) {return simulateBuilderlessNamingManager(requestedFactory);}return new CloseSafeMemoryContextFactory();
}

方法simulateBuilderlessNamingManager使用类加载器加载请求的上下文工厂:

private InitialContextFactory simulateBuilderlessNamingManager(String requestedFactory) throws NoInitialContextException {try {ClassLoader cl = getContextClassLoader();Class requestedClass = Class.forName(className, true, cl);return (InitialContextFactory) requestedClass.newInstance();} catch (Exception e) {NoInitialContextException ne = new NoInitialContextException(...);ne.setRootCause(e);throw ne;}
}private ClassLoader getContextClassLoader() {return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {public Object run() {return Thread.currentThread().getContextClassLoader();}});
}

构建器安装和上下文清理

最后,我们必须安装上下文工厂生成器。 当我们想在测试中使用独立的JNDI时,我们还需要一种方法来清除测试之间的所有存储数据。 两者都在initializeJNDI方法内部完成,该方法将在每次测试之前运行:

public class JNDIUtil {public void initializeJNDI() {if (jndiInitialized()) {cleanAllInMemoryData();} else {installDefaultContextFactoryBuilder();}}}

如果已经设置了默认上下文工厂构建器,那么将初始化JNDI:

private boolean jndiInitialized() {return NamingManager.hasInitialContextFactoryBuilder();}

安装默认上下文工厂生成器:

private void installDefaultContextFactoryBuilder() {try {NamingManager.setInitialContextFactoryBuilder(new ImMemoryDefaultContextFactoryBuilder());} catch (NamingException e) {//We can not solve the problem. We will let it go up without//having to declare the exception every time.throw new ConfigurationException(e);}
}

使用原始的方法实现closeMemoryContext类清理存储数据:

private void cleanAllInMemoryData() {CleanerContext cleaner = new CleanerContext();try {cleaner.close();} catch (NamingException e) {throw new RuntimeException("Memory context cleaning failed:", e);}
}class CleanerContext extends MemoryContext {private static Hashtable environnement = new Hashtable();static {environnement.put("org.osjava.sj.jndi.shared", "true");}public CleanerContext() {super(environnement);}}


内存数据库

Apache Derby是用Java实现的开源关系数据库。 根据Apache许可证2.0版提供。 Derby能够在嵌入式模式下运行。 嵌入式数据库数据存储在文件系统或内存中。

对Derby的Maven依赖关系:

org.apache.derbyderby10.8.2.2

创建数据源

使用EmbeddedDatasource类的实例连接到数据库。 每当数据库名称以“ memory:”开头时,数据源将使用一个内存中实例。

以下代码创建指向内存数据库实例的数据源。 如果数据库尚不存在,将创建它:

private EmbeddedDataSource createDataSource() {EmbeddedDataSource dataSource = new EmbeddedDataSource();dataSource.setDataSourceName(dataSourceJndiName);dataSource.setDatabaseName("memory:" + databaseName);dataSource.setCreateDatabase("create");return dataSource;
}

删除数据库

清理数据库的最简单方法是删除并重新创建它。 创建嵌入式数据源的实例,将连接属性“ drop”设置为“ true”,并调用其getConnection方法。 它将删除数据库并引发异常。

private static final String DATABASE_NOT_FOUND = "XJ004";private void dropDatabase() {EmbeddedDataSource dataSource = createDataSource();dataSource.setCreateDatabase(null);dataSource.setConnectionAttributes("drop=true");try {//drop the database; not the nicest solution, but worksdataSource.getConnection();} catch (SQLNonTransientConnectionException e) {//this is OK, database was dropped} catch (SQLException e) {if (DATABASE_NOT_FOUND.equals(e.getSQLState())) {//attempt to drop non-existend database//we will ignore this errorreturn ; }throw new ConfigurationException("Could not drop database.", e);}}


数据库结构

我们使用Liquibase创建数据库结构和测试数据。 数据库结构保存在所谓的变更日志文件中。 它是一个xml文件,但是如果您不想学习另一种xml语言,则可以包含DDL或SQL代码。

Liquibase及其优点不在本文讨论范围之内。 此演示最相关的优势是它能够对同一数据库多次运行同一变更日志。 每次运行仅将新更改应用于数据库。 如果文件未更改,则什么都不会发生。

您可以将更改日志添加到jar或war中,并在每次启动应用程序时运行它。 这样可以确保数据库始终更新为最新版本。 无需配置或安装脚本。

将Liquibase依赖项添加到pom.xml:

org.liquibaseliquibase-core2.0.3

以下更新日志创建一个名为Person的表,并将一个条目“斜杠– Simon Worth”放入其中:

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd"><changeSet id="1" author="meri"><comment>Create table structure for users and shared items.</comment><createTable tableName="person"><column name="user_id" type="integer"><constraints primaryKey="true" nullable="false" /></column><column name="username" type="varchar(1500)"><constraints unique="true" nullable="false" /></column><column name="firstname" type="varchar(1500)"/><column name="lastname" type="varchar(1500)"/><column name="homepage" type="varchar(1500)"/><column name="about" type="varchar(1500)"/></createTable></changeSet><changeSet id="2" author="meri" context="test"><comment>Add some test data.</comment><insert tableName="person"><column name="user_id" valueNumeric="1" /><column name="userName" value="slash" /><column name="firstName" value="Simon" /><column name="lastName" value="Worth" /><column name="homePage" value="http://www.slash.blogs.net" /><column name="about" value="I like nature and writing my blog. The blog contains my opinions about everything." /></insert></changeSet></databaseChangeLog>

Liquibase的使用非常简单。 使用数据源创建新的Liquibase实例,运行其update方法并处理所有声明的异常:

private void initializeDatabase(String changelogPath, DataSource dataSource) {try {//create new liquibase instanceConnection sqlConnection = dataSource.getConnection();DatabaseConnection db = new DerbyConnection(sqlConnection);Liquibase liquibase = new Liquibase(changelogPath, new FileSystemResourceAccessor(), db);//update the databaseliquibase.update("test");} catch (SQLException e) {// We can not solve the problem. We will let it go up without// having to declare the exception every time.throw new ConfigurationException(DB_INITIALIZATION_ERROR, e);} catch (LiquibaseException e) {// We can not solve the problem. We will let it go up without// having to declare the exception every time.throw new ConfigurationException(DB_INITIALIZATION_ERROR, e);}}


结束

每次运行测试时,独立的JNDI数据库和嵌入式内存数据库都已启动并正在运行。 尽管JNDI设置可能是通用的,但数据库的构建可能需要对项目进行特定的修改。

可以从Github上免费下载示例项目,并使用/修改任何有用的内容。

参考:在This is Stuff博客上,我们的JCG合作伙伴 Maria Jurcovicova从JNDI和JPA Without J2EE Con​​tainer运行 。


翻译自: https://www.javacodegeeks.com/2012/04/jndi-and-jpa-without-j2ee-container.html

jpa jdbc jndi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/355870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本科计算机应用水平,湖南工程学院全日制非计算机专业本科生参加湖南省计算机应用水平等级考试的规定...

根据省教育厅《关于印发湖南省普通高等学校非计算机专业学生计算机应用水平等级考试大纲的通知》(湘教发〔2012〕58号)精神&#xff0c;经研究&#xff0c;现对我校全日制非计算机专业本科生参加计算机等级考试有关事项作如下规定&#xff1a;1&#xff0e;凡我校全日制非计算机…

Linux umask限制导致php的mkdir 0777无效

原因:mkdir权限受当前linux umask限制 解决方法: 1 $oldmask umask(0); 2 mkdir("test", 0777); 3 umask($oldmask); 参考SO:http://stackoverflow.com/a/3997671/4009148转载于:https://www.cnblogs.com/gy1010/p/6674243.html

cstringw转lpctstr_新手必看:CString 和 LPCTSTR等之间的转换大全 | 求索阁

CString 和 LPCTSTR 可以说通用。 原因在于CString定义的自动类型转换&#xff0c;没什么奇特的&#xff0c;最简单的C操作符重载而已。常量字符串ansi和unicode的区分是由宏_T来决定的。但是用_T( "abcd ")时&#xff0c; 字符串 "abcd "就会根…

vue如何过滤html标签,去除富文本中的html标签及vue、react、微信小顺序中的过滤器...

在猎取富文本后&#xff0c;又只需显现部分内容&#xff0c;须要去除富文本标签&#xff0c;然后再截取个中一部分内容&#xff1b;然后就是过滤器&#xff0c;在微信小顺序中运用照样挺屡次的&#xff0c;在vue及react中也遇到过1.富文本去除html标签去除html标签及 空格let r…

在基于简单Vertx Rest的应用程序上为REST资源设置基本响应HTTP标头

我是Vert.x的新手&#xff0c;但是作为Java开发人员&#xff08;非常努力&#xff09;&#xff0c;与NodeJS或其他任何基于Reactor的框架/库相比&#xff0c;我觉得它更加有趣并且很有前途。 因此&#xff0c;我正在使用Vert.x实现一个非常简单的Restful API。 今天的问题是我…

OAuth2认证有一定的了解

转到分享界面后&#xff0c;进行OAuth2认证&#xff1a; 以新浪为例&#xff1a; 第一步、WebView加载界面&#xff0c;传递参数 使用WebView加载登陆网页&#xff0c;通过Get方法传递三个参数&#xff1a;应用的appkey、回调地址和展示方式display(如手机设备为mobile)&#x…

声速的测量的实验原理和应用_CEMS烟气在线分析仪测量原理计经典应用

烟气连续在线监测系统运用抽取冷凝采样、后散射烟尘浓度测量、皮托管烟气流速测量及计算机网络通讯技术&#xff0c;实现了固定污染源污染物排放浓度和排放总量的在线连续监测。同时又针对国内煤种较杂、煤质变化大、污染物排放浓度高、烟气湿度大的状况从技术上进行了改进。并…

怎么用计算机算弧度制,怎么设置计算器 把度数转化为弧度

计算器默认角度制(D)。此时&#xff0c;按下mode&#xff0c;mode&#xff0c;2(Rad)&#xff0c;可将计算器调整为弧度制。输入要转化的角度(如30)&#xff0c;按下shift&#xff0c;ans(DRG三角)&#xff0c;1(D)&#xff0c;画面将显示30度&#xff0c;按下等号&#xff0c;…

Python 类方法、实例方法、静态方法

实例方法&#xff1a;类中第一个参数为self的方法。 类方法&#xff1a;类中第一个参数为类&#xff0c;约定写为cls&#xff0c;并被classmethod修饰的方法。 静态方法&#xff1a;类中被staticmethod修饰的方法。 类变量&#xff1a;定义在类的定义之后&#xff0c;如&#x…

python 方程组 整数解_用Python语言求解线性整数方程组

我在寻找一种用Python求解线性方程组的方法。特别是&#xff0c;我在寻找大于所有零的最小整数向量&#xff0c;并解出给定的方程。例如&#xff0c;我有以下等式&#xff1a;想解决。在在这种情况下&#xff0c;求解该方程的最小整数向量为。在但是&#xff0c;如何自动确定此…

计算机软件水平考试调整,全国计算机等级考试调整方案

考生们注意&#xff1a;在新的历史时期&#xff0c;全国计算机等级考试将在保持自身特色&#xff0c;稳定发展的基础上进一步推进考试改革&#xff0c;从2018年3月起&#xff0c;教育部考试中心将实施2018年考试大纲&#xff0c;并按新体系开考各个考试级别&#xff0c;希望能帮…

javaserver_集成Spring和JavaServer Faces:改进的模板

javaserver随着2.0版的发布&#xff0c;Facelet模板成为JSF规范的核心部分。 使用<ui&#xff1a;composition>和<ui&#xff1a;decorate>标记&#xff0c;可以轻松构建复杂的页面&#xff0c;同时仍保持标记的整洁。 模板在创建HTML表单时特别有用&#xff0c;但…

datagrid 什么时候结束编辑_孕吐到底什么时候结束

很多女性刚怀孕&#xff0c;都会出现妊娠反应&#xff0c;比如孕吐。它是由妊娠后绒毛分泌的绒毛膜促进腺激素引起的&#xff0c;在妊娠初期腺激素分泌量较多。备受孕吐折磨的女性&#xff0c;每次吃饭&#xff0c;一闻到刺激性味道&#xff0c;就会想吐&#xff0c;非常难受&a…

201521123032 《Java程序设计》第7周学习总结

1. 本周学习总结 以你喜欢的方式&#xff08;思维导图或其他&#xff09;归纳总结集合相关内容。 2. 书面作业 ArrayList代码分析 1.1 解释ArrayList的contains源代码 在contains方法中调用indexOF方法&#xff0c;首先比较下标o&#xff0c;如果onull那么elementData[]中是否n…

计算机图形图像电影论文,计算机图形图像绘制技术地现状分析及应用发展.doc...

计算机图形图像绘制技术地现状分析及应用发展计算机图形图像绘制技术的现状分析及应用发展-计算机论文计算机图形图像绘制技术的现状分析及应用发展金晓倩 JIN Xiao-qian(四川建筑职业技术学院&#xff0c;德阳618000)(Sichuan College of Architectural Technology&#xff0c…

Java EE 7之前版本替代JPA 2.1的非同步持久性上下文

Java EE 7中的非同步持久性上下文 JPA 2.1引入了非同步持久性上下文的概念&#xff0c;该概念允许对JPA实体管理器的刷新进行细粒度控制&#xff0c;即通过显式调用EntityManager&#xff03;joinTransaction 。 以前&#xff0c;这默认情况下是JTA事务的结束&#xff0c;例如&…

三相同步电机怎么接线图_三相电度表怎么看倍数

电工之家&#xff1a;www.dgzj.com QQ群&#xff1a;2179090关注电工之家官方微信公众号“电工之家”&#xff0c;收获更多经验知识。从题主给的照片来看&#xff0c;这个电度表型号是DTS901-4 1.5(6)A 3X220V/380V精确度为1的1级互感器间接接线的三相四线有功电子电度表。那…

第七周进度表

所花时间 7   代码量&#xff08;行&#xff09; 235 博客量 2 所学知识点 了解了结队开发 转载于:https://www.cnblogs.com/muxiaozhou/p/6993180.html

中国计量大学调剂计算机技术,2020年中国计量大学硕士研究生招生调剂公告

一、调剂分数线&#xff1a;详见《中国计量大学2020年硕士研究生招生复试分数线》。二、调剂程序&#xff1a;1.第一阶段&#xff1a;登陆我校“研究生招生信息系统”网址https://yjsb.cjlu.edu.cn/yjszs_xsb/登记调剂信息。此信息用于复试&#xff0c;请务必认真准确填写。2.第…

linux msgrcv阻塞接收_linux下高并发服务器实现

在做网络服务的时候tcp并发服务端程序的编写必不可少。tcp并发通常有几种固定的设计模式套路&#xff0c;他们各有优点&#xff0c;也各有应用之处。下面就简单的讨论下这几种模式的差异&#xff1a;单进程&#xff0c;单线程在accept之后&#xff0c;就开始在这一个连接连接上…