我正在尝试通过将Swing
配置为自动(和可移植)来扩展我的库以集成JPA
和JPA
,这意味着以编程方式添加{{ 1}}元素。 (我知道它可以通过Hibernate的<class>
或EclipseLInk的AnnotationConfiguration
完成,但是 - 可移植性)。我也想避免仅仅为了这个目的使用ServerSession
。
我可以动态创建Spring
,并使用指定包中的persistence.xml
元素填充它(通过Reflections库)。当我尝试将此<class>
提供给persistence.xml
提供商时,问题就会出现。我能想到的唯一方法就是设置一个JPA
,但我想不出一种方法,首先不能让我把文件写到磁盘上,因为它只能获得有效的{{{ 1}}。通过URLClassLoader
(URL
)设置套接字来提供文件似乎......我不知道,邪恶?
有谁知道如何解决这个问题?我知道避免使用一个库听起来有很多工作,但我想知道是否可以完成。
编辑(尝试更清楚):
动态生成的URL
保存在localhost:xxxx
对象中。我不知道如何将它提供给持久性提供程序。另外,我想避免将文件写入磁盘。
出于我的问题的目的,持久性提供程序只是一个扫描类XML
的类路径的类。可以使用某些实现来接受String
的动态创建,但是没有通用接口(特别是对于文件的关键部分,META-INF/persistence.xml
标记)。
我的想法是设置一个自定义的XML
- 如果你有任何其他的我会感激,我不会参与其中。
我能找到的唯一易于扩展/可配置的是<class>
。它适用于ClassLoader
个对象,我不知道是否可以先创建一个而不先将XML写入磁盘。
这就是我正在设置的方式,但它的工作原理是将URLClassLoader
写入磁盘:
URL
persistenceXmlFile = new File("META-INF/persistence.xml")
是Thread.currentThread().setContextClassLoader(
new URLResourceClassLoader(
new URL[] { persistenceXmlFile.toURI().toURL() },
Thread.currentThread().getContextClassLoader()
)
);
的子类,它允许通过覆盖URLResourceClassLoader
来查找资源和类。
答案 0 :(得分:7)
也许有点晚了(4年后),但是对于那些正在寻找类似解决方案的人来说,你可以使用我创建的URL工厂:
public class InMemoryURLFactory {
public static void main(String... args) throws Exception {
URL url = InMemoryURLFactory.getInstance().build("/this/is/a/test.txt", "This is a test!");
byte[] data = IOUtils.toByteArray(url.openConnection().getInputStream());
// Prints out: This is a test!
System.out.println(new String(data));
}
private final Map<URL, byte[]> contents = new WeakHashMap<>();
private final URLStreamHandler handler = new InMemoryStreamHandler();
private static InMemoryURLFactory instance = null;
public static synchronized InMemoryURLFactory getInstance() {
if(instance == null)
instance = new InMemoryURLFactory();
return instance;
}
private InMemoryURLFactory() {
}
public URL build(String path, String data) {
try {
return build(path, data.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
}
public URL build(String path, byte[] data) {
try {
URL url = new URL("memory", "", -1, path, handler);
contents.put(url, data);
return url;
} catch (MalformedURLException ex) {
throw new RuntimeException(ex);
}
}
private class InMemoryStreamHandler extends URLStreamHandler {
@Override
protected URLConnection openConnection(URL u) throws IOException {
if(!u.getProtocol().equals("memory")) {
throw new IOException("Cannot handle protocol: " + u.getProtocol());
}
return new URLConnection(u) {
private byte[] data = null;
@Override
public void connect() throws IOException {
initDataIfNeeded();
checkDataAvailability();
// Protected field from superclass
connected = true;
}
@Override
public long getContentLengthLong() {
initDataIfNeeded();
if(data == null)
return 0;
return data.length;
}
@Override
public InputStream getInputStream() throws IOException {
initDataIfNeeded();
checkDataAvailability();
return new ByteArrayInputStream(data);
}
private void initDataIfNeeded() {
if(data == null)
data = contents.get(u);
}
private void checkDataAvailability() throws IOException {
if(data == null)
throw new IOException("In-memory data cannot be found for: " + u.getPath());
}
};
}
}
}
答案 1 :(得分:0)
我们可以为此使用 Jimfs 谷歌库。
首先,我们需要将 maven dependency 添加到我们的项目中:
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<version>1.2</version>
</dependency>
之后,我们需要配置我们的文件系统行为,并将我们的字符串内容写入内存文件,如下所示:
public static final String INPUT =
"\n"
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<note>\n"
+ " <to>Tove</to>\n"
+ " <from>Jani</from>\n"
+ " <heading>Reminder</heading>\n"
+ " <body>Don't forget me this weekend!</body>\n"
+ "</note>";
@Test
void usingJIMFS() throws IOException {
try (var fs = Jimfs.newFileSystem(Configuration.unix())) {
var path = fs.getPath(UUID.randomUUID().toString());
Files.writeString(path, INPUT);
var url = path.toUri().toURL();
assertThat(url.getProtocol()).isEqualTo("jimfs");
assertThat(Resources.asCharSource(url, UTF_8).read()).isEqualTo(INPUT);
}
}
我们可以在 official repository 中找到更多示例。
如果我们查看 jimfs source code 的内部,我们会发现实现类似于 @NSV 答案。