4
4
*/
5
5
package org .hibernate .orm .test .envers .integration .blob ;
6
6
7
- import static org .hamcrest .MatcherAssert .assertThat ;
8
- import static org .hibernate .testing .transaction .TransactionUtil .doInJPA ;
9
- import static org .junit .Assert .fail ;
7
+ import jakarta .persistence .Entity ;
8
+ import jakarta .persistence .GeneratedValue ;
9
+ import jakarta .persistence .Id ;
10
+ import org .hamcrest .Matchers ;
11
+ import org .hibernate .dialect .PostgreSQLDialect ;
12
+ import org .hibernate .dialect .SQLServerDialect ;
13
+ import org .hibernate .engine .jdbc .BlobProxy ;
14
+ import org .hibernate .envers .Audited ;
15
+ import org .hibernate .orm .test .envers .BaseEnversJPAFunctionalTestCase ;
16
+ import org .hibernate .orm .test .envers .Priority ;
17
+ import org .hibernate .testing .SkipForDialect ;
18
+ import org .junit .Test ;
10
19
11
20
import java .io .BufferedInputStream ;
12
21
import java .io .InputStream ;
13
22
import java .nio .file .Files ;
14
23
import java .nio .file .Path ;
15
24
import java .sql .Blob ;
16
25
17
- import org .hamcrest .Matchers ;
18
- import org .hibernate .engine .jdbc .proxy .BlobProxy ;
19
- import org .hibernate .envers .Audited ;
20
- import org .hibernate .orm .test .envers .BaseEnversJPAFunctionalTestCase ;
21
- import org .hibernate .orm .test .envers .Priority ;
22
- import org .junit .Test ;
23
-
24
- import jakarta .persistence .Entity ;
25
- import jakarta .persistence .GeneratedValue ;
26
- import jakarta .persistence .Id ;
26
+ import static org .hamcrest .MatcherAssert .assertThat ;
27
+ import static org .hibernate .testing .transaction .TransactionUtil .doInJPA ;
28
+ import static org .junit .Assert .fail ;
27
29
28
30
/**
29
31
* @author Chris Cranford
@@ -32,19 +34,19 @@ public class BasicBlobTest extends BaseEnversJPAFunctionalTestCase {
32
34
33
35
@ Override
34
36
protected Class <?>[] getAnnotatedClasses () {
35
- return new Class <?>[] { Asset .class };
37
+ return new Class <?>[] {Asset .class };
36
38
}
37
39
38
40
@ Test
39
41
@ Priority (10 )
40
- public void initData () {
41
- final Path path = Path .of ( getClass ().getResource ( "./blob.txt" ).getPath () );
42
+ public void testGenerateProxyNoStream () {
43
+ final Path path = Path .of ( Thread .currentThread ().getContextClassLoader ()
44
+ .getResource ( "org/hibernate/orm/test/envers/integration/blob/blob.txt" ).getPath () );
42
45
doInJPA ( this ::entityManagerFactory , entityManager -> {
43
- try {
44
- final Asset asset = new Asset ();
45
- asset .setFileName ( "blob.txt" );
46
+ final Asset asset = new Asset ();
47
+ asset .setFileName ( "blob.txt" );
46
48
47
- final InputStream stream = new BufferedInputStream ( Files .newInputStream ( path ) );
49
+ try ( final InputStream stream = new BufferedInputStream ( Files .newInputStream ( path ) )) {
48
50
assertThat ( stream .markSupported (), Matchers .is ( true ) );
49
51
50
52
// We use the method readAllBytes instead of passing the raw stream to the proxy
@@ -70,6 +72,49 @@ public void initData() {
70
72
fail ( "Failed to persist the entity" );
71
73
}
72
74
} );
75
+
76
+ }
77
+
78
+ @ Test
79
+ @ Priority (10 )
80
+ @ SkipForDialect (value = PostgreSQLDialect .class ,
81
+ comment = "The driver closes the stream, so it cannot be reused by envers" )
82
+ @ SkipForDialect (value = SQLServerDialect .class ,
83
+ comment = "The driver closes the stream, so it cannot be reused by envers" )
84
+ public void testGenerateProxyStream () {
85
+ final Path path = Path .of ( Thread .currentThread ().getContextClassLoader ()
86
+ .getResource ( "org/hibernate/orm/test/envers/integration/blob/blob.txt" ).getPath () );
87
+
88
+ try (final InputStream stream = new BufferedInputStream ( Files .newInputStream ( path ) )) {
89
+ doInJPA ( this ::entityManagerFactory , entityManager -> {
90
+ final Asset asset = new Asset ();
91
+ asset .setFileName ( "blob.txt" );
92
+
93
+ assertThat ( stream .markSupported (), Matchers .is ( true ) );
94
+
95
+ // We use the method readAllBytes instead of passing the raw stream to the proxy
96
+ // since this is the only guaranteed way that will work across all dialects in a
97
+ // deterministic way. Postgres and Sybase will automatically close the stream
98
+ // after the blob has been written by the driver, which prevents Envers from
99
+ // then writing the contents of the stream to the audit table.
100
+ //
101
+ // If the driver and dialect are known not to close the input stream after the
102
+ // contents have been written by the driver, then it's safe to pass the stream
103
+ // here instead and the stream will be automatically marked and reset so that
104
+ // Envers can serialize the data after Hibernate has done so. Dialects like
105
+ // H2, MySQL, Oracle, SQL Server work this way.
106
+ //
107
+ //
108
+ Blob blob = BlobProxy .generateProxy ( stream , 9192L );
109
+
110
+ asset .setData ( blob );
111
+ entityManager .persist ( asset );
112
+ } );
113
+ }
114
+ catch (Exception e ) {
115
+ e .printStackTrace ();
116
+ fail ( "Failed to persist the entity" );
117
+ }
73
118
}
74
119
75
120
@ Audited
0 commit comments