| /* |
| * Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved. |
| * Copyright (c) 2019 IBM Corporation. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // IBM - initial drop |
| // 05/06/2019 - Jody Grassel |
| // - 547023 : Add LOB Locator support for core Oracle platform. |
| |
| package org.eclipse.persistence.jpa.test.oraclefeatures; |
| |
| import java.security.SecureRandom; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import jakarta.persistence.EntityManager; |
| import jakarta.persistence.EntityManagerFactory; |
| |
| import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl; |
| import org.eclipse.persistence.jpa.test.framework.DDLGen; |
| import org.eclipse.persistence.jpa.test.framework.Emf; |
| import org.eclipse.persistence.jpa.test.framework.EmfRunner; |
| import org.eclipse.persistence.jpa.test.framework.Property; |
| import org.eclipse.persistence.jpa.test.oraclefeatures.model.OracleLobEntity; |
| import org.eclipse.persistence.platform.database.DatabasePlatform; |
| import org.eclipse.persistence.platform.database.OraclePlatform; |
| |
| import org.hamcrest.BaseMatcher; |
| import org.hamcrest.Description; |
| import org.hamcrest.Matcher; |
| |
| import org.hamcrest.MatcherAssert; |
| import org.junit.Assert; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| @RunWith(EmfRunner.class) |
| public class TestOracleLOBLocatorFeature { |
| private final static char[] alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghikjlmnopqrstuvwxyz".toCharArray(); |
| private final static int alphaLen = alphabet.length; |
| |
| @Emf(name = "emfWithSessionCustomizer",createTables = DDLGen.DROP_CREATE, classes = { OracleLobEntity.class }, properties = { |
| @Property(name = "eclipselink.session.customizer", value="org.eclipse.persistence.jpa.test.oraclefeatures.OracleLOBLocatorSessionCustomizer") |
| // @Property(name = "eclipselink.logging.level", value = "FINEST"), |
| }) |
| private EntityManagerFactory emf; |
| |
| @Emf(name = "emfNoSessionCustomizer", createTables = DDLGen.DROP_CREATE, classes = { OracleLobEntity.class }) |
| private EntityManagerFactory emfNoSessionCustomizer; |
| |
| |
| private SecureRandom sr = new SecureRandom(); |
| |
| @Test |
| public void testOracleLOBLocator() throws Exception { |
| if (!checkIsOracle()) { |
| // Skip if not testing against Oracle |
| return; |
| } |
| |
| System.out.println("***** Begin testOracleLOBLocator"); |
| |
| EntityManager em = emf.createEntityManager(); |
| try { |
| OracleLobEntity blobEntity = new OracleLobEntity(); |
| blobEntity.setStrData("Some Data"); |
| |
| int datalen = 50000; |
| byte[] data = new byte[datalen]; |
| sr.nextBytes(data); |
| blobEntity.setBlobData(data); |
| |
| char[] cdata = new char[datalen]; |
| for (int i = 0; i < datalen; i++) { |
| cdata[i] = alphabet[Math.abs((sr.nextInt() % alphaLen))]; |
| } |
| blobEntity.setClobData(new String(cdata)); |
| |
| em.getTransaction().begin(); |
| em.persist(blobEntity); |
| em.getTransaction().commit(); |
| |
| em.clear(); |
| |
| OracleLobEntity findEntity = em.find(OracleLobEntity.class, blobEntity.getId()); |
| Assert.assertNotNull(findEntity); |
| Assert.assertEquals(blobEntity.getStrData(), findEntity.getStrData()); |
| Assert.assertEquals(blobEntity.getBlobData(), findEntity.getBlobData()); |
| Assert.assertEquals(blobEntity.getClobData(), findEntity.getClobData()); |
| } finally { |
| if(em != null) { |
| if (em.getTransaction().isActive()) { |
| em.getTransaction().rollback(); |
| } |
| if(em.isOpen()) { |
| em.close(); |
| } |
| } |
| System.out.println("***** End testOracleLOBLocator"); |
| } |
| } |
| |
| @Test |
| public void testOracleLOBLocatorWithEmptyClob() throws Exception { |
| if (!checkIsOracle()) { |
| // Skip if not testing against Oracle |
| return; |
| } |
| |
| System.out.println("***** Begin testOracleLOBLocatorWithEmptyClob"); |
| |
| EntityManager em = emf.createEntityManager(); |
| try { |
| OracleLobEntity blobEntity = new OracleLobEntity(); |
| blobEntity.setStrData("Some Data"); |
| |
| int datalen = 50000; |
| byte[] data = new byte[datalen]; |
| sr.nextBytes(data); |
| blobEntity.setBlobData(data); |
| |
| blobEntity.setClobData(""); |
| |
| em.getTransaction().begin(); |
| em.persist(blobEntity); |
| em.getTransaction().commit(); |
| |
| em.clear(); |
| |
| OracleLobEntity findEntity = em.find(OracleLobEntity.class, blobEntity.getId()); |
| Assert.assertNotNull(findEntity); |
| Assert.assertEquals(blobEntity.getStrData(), findEntity.getStrData()); |
| Assert.assertEquals(blobEntity.getBlobData(), findEntity.getBlobData()); |
| Assert.assertEquals(blobEntity.getClobData(), findEntity.getClobData()); |
| } finally { |
| if(em != null) { |
| if (em.getTransaction().isActive()) { |
| em.getTransaction().rollback(); |
| } |
| if(em.isOpen()) { |
| em.close(); |
| } |
| } |
| System.out.println("***** End testOracleLOBLocatorWithEmptyClob"); |
| } |
| } |
| |
| @Test |
| public void testOracleWithoutLOBLocatorWithEmptyClob() throws Exception { |
| // After Oracle 11, the lob locator is disabled by default (requiring a Session Customizer to reenable it) |
| // So the test should fail because Eclipselink will try store a null value instead of an empty_blob()/empty_clob() |
| // and violate the NOT NULL constraint. |
| Set<String> notAllowedPlatforms = new HashSet<String>(); |
| notAllowedPlatforms.add("org.eclipse.persistence.platform.database.Oracle8Platform"); |
| notAllowedPlatforms.add("org.eclipse.persistence.platform.database.Oracle9Platform"); |
| notAllowedPlatforms.add("org.eclipse.persistence.platform.database.Oracle10Platform"); |
| |
| |
| if (!checkIsOracle() || notAllowedPlatforms.contains(getPlatform(emfNoSessionCustomizer).getClass().getName())) { |
| // Skip if not testing against Oracle |
| return; |
| } |
| |
| System.out.println("***** Begin testOracleWithoutLOBLocatorWithEmptyClob"); |
| |
| EntityManager em = emfNoSessionCustomizer.createEntityManager(); |
| try { |
| OracleLobEntity blobEntity = new OracleLobEntity(); |
| blobEntity.setStrData("Some Data"); |
| |
| int datalen = 50000; |
| byte[] data = new byte[datalen]; |
| sr.nextBytes(data); |
| blobEntity.setBlobData(data); |
| |
| blobEntity.setClobData(""); |
| |
| try { |
| em.getTransaction().begin(); |
| em.persist(blobEntity); |
| em.getTransaction().commit(); |
| } catch (jakarta.persistence.RollbackException re) { |
| // Expected |
| MatcherAssert.assertThat(re, getExceptionChainMatcher(java.sql.SQLIntegrityConstraintViolationException.class)); |
| } |
| |
| |
| } finally { |
| if(em != null) { |
| if (em.getTransaction().isActive()) { |
| em.getTransaction().rollback(); |
| } |
| if(em.isOpen()) { |
| em.close(); |
| } |
| } |
| System.out.println("***** End testOracleWithoutLOBLocatorWithEmptyClob"); |
| } |
| } |
| |
| |
| private boolean checkIsOracle() { |
| return (emf != null && getPlatform(emf) instanceof OraclePlatform); |
| } |
| |
| private DatabasePlatform getPlatform(EntityManagerFactory emf) { |
| DatabasePlatform platform = ((EntityManagerFactoryImpl) emf).getServerSession().getPlatform(); |
| return platform; |
| } |
| |
| @SuppressWarnings("rawtypes") |
| protected Matcher getExceptionChainMatcher(final Class<?> t) { |
| return new BaseMatcher() { |
| final protected Class<?> expected = t; |
| |
| @Override |
| public boolean matches(Object obj) { |
| if (obj == null) { |
| return (expected == null); |
| } |
| |
| if (!(obj instanceof Throwable)) { |
| return false; |
| } |
| |
| final ArrayList<Throwable> tList = new ArrayList<Throwable>(); |
| |
| Throwable t = (Throwable) obj; |
| while (t != null) { |
| tList.add(t); |
| if (expected.equals(t.getClass())) { |
| return true; |
| } |
| |
| if (expected.isAssignableFrom(t.getClass())) { |
| return true; |
| } |
| |
| t = t.getCause(); |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public void describeTo(Description description) { |
| description.appendText(expected.toString()); |
| } |
| |
| }; |
| } |
| |
| } |