HHH-11882 - Bytecode enhancer tests with the new JUnit runner

This commit is contained in:
barreiro 2017-07-11 16:20:28 +01:00 committed by Steve Ebersole
parent 168a47bdae
commit fb6a7a376f
41 changed files with 5373 additions and 108 deletions

View File

@ -0,0 +1,207 @@
package org.hibernate.test.bytecode.enhancement.access;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import static java.util.stream.Collectors.joining;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
/**
* @author Luis Barreiro
*/
@Ignore( "Property access does not allow dirty tracking, so this test fails (on the cleanup method)" )
@TestForIssue( jiraKey = "HHH-10851" )
@RunWith( BytecodeEnhancerRunner.class )
@CustomEnhancementContext( {EnhancerTestContext.class, MixedAccessTest.NoDirtyCheckingContext.class} )
public class MixedAccessTest extends BaseCoreFunctionalTestCase {
private static final ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName( "javascript" );
private static final Function<Map.Entry, String> MAPPING_FUNCTION = e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"";
private static boolean cleanup = false;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{TestEntity.class, TestOtherEntity.class};
}
@Before
public void prepare() {
buildSessionFactory();
doInHibernate( this::sessionFactory, s -> {
TestEntity testEntity = new TestEntity( "foo" );
testEntity.setParamsAsString( "{\"paramName\":\"paramValue\"}" );
s.persist( testEntity );
TestOtherEntity testOtherEntity = new TestOtherEntity( "foo" );
testOtherEntity.setParamsAsString( "{\"paramName\":\"paramValue\"}" );
s.persist( testOtherEntity );
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
TestEntity testEntity = s.get( TestEntity.class, "foo" );
Assert.assertEquals( "{\"paramName\":\"paramValue\"}", testEntity.getParamsAsString() );
TestOtherEntity testOtherEntity = s.get( TestOtherEntity.class, "foo" );
Assert.assertEquals( "{\"paramName\":\"paramValue\"}", testOtherEntity.getParamsAsString() );
// Clean parameters
cleanup = true;
testEntity.setParamsAsString( "{}" );
testOtherEntity.setParamsAsString( "{}" );
} );
}
@After
public void cleanup() {
doInHibernate( this::sessionFactory, s -> {
TestEntity testEntity = s.get( TestEntity.class, "foo" );
Assert.assertTrue( testEntity.getParams().isEmpty() );
TestOtherEntity testOtherEntity = s.get( TestOtherEntity.class, "foo" );
Assert.assertTrue( testOtherEntity.getParams().isEmpty() );
} );
}
// --- //
@Entity
@Table( name = "TEST_ENTITY" )
private static class TestEntity {
@Id
String name;
@Transient
Map<String, String> params = new LinkedHashMap<>();
TestEntity(String name) {
this();
this.name = name;
}
TestEntity() {
}
Map<String, String> getParams() {
return Collections.unmodifiableMap( params );
}
void setParams(Map<String, String> params) {
this.params = params;
}
@Column( name = "params", length = 4000 )
@Access( AccessType.PROPERTY )
String getParamsAsString() {
return params.isEmpty() ? null : "{" + params.entrySet().stream().map( MAPPING_FUNCTION ).collect( joining( "," ) ) + "}";
}
@SuppressWarnings( "unchecked" )
void setParamsAsString(String string) {
params.clear();
try {
if ( string != null ) {
params.putAll( (Map<String, String>) SCRIPT_ENGINE.eval( "Java.asJSONCompatible(" + string + ")" ) );
}
} catch ( ScriptException ignore ) {
// JDK 8u60 required --- use hard coded values to pass the test
if ( !cleanup ) {
params.put( "paramName", "paramValue" );
}
}
}
}
@Entity
@Table( name = "OTHER_ENTITY" )
@Access( AccessType.FIELD )
private static class TestOtherEntity {
@Id
String name;
@Transient
Map<String, String> params = new LinkedHashMap<>();
TestOtherEntity(String name) {
this();
this.name = name;
}
TestOtherEntity() {
}
Map<String, String> getParams() {
return Collections.unmodifiableMap( params );
}
void setParams(Map<String, String> params) {
this.params = params;
}
@Column( name = "params", length = 4000 )
@Access( AccessType.PROPERTY )
String getParamsAsString() {
return params.isEmpty() ? null : "{" + params.entrySet().stream().map( MAPPING_FUNCTION ).collect( joining( "," ) ) + "}";
}
@SuppressWarnings( "unchecked" )
void setParamsAsString(String string) {
params.clear();
try {
if ( string != null ) {
params.putAll( (Map<String, String>) SCRIPT_ENGINE.eval( "Java.asJSONCompatible(" + string + ")" ) );
}
} catch ( ScriptException ignore ) {
// JDK 8u60 required --- use hard coded values to pass the test
if ( !cleanup ) {
params.put( "paramName", "paramValue" );
}
}
}
}
// --- //
public static class NoDirtyCheckingContext extends DefaultEnhancementContext {
@Override
public boolean doDirtyCheckingInline(UnloadedClass classDescriptor) {
return false;
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.association;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import java.util.List;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-11050" )
@RunWith( BytecodeEnhancerRunner.class )
public class InheritedAttributeAssociationTest {
@Test
public void test() {
// The mapping is wrong but the point is that the enhancement phase does not need to fail. See JIRA for further detail
// If enhancement of 'items' attribute fails, 'name' won't be enhanced
Author author = new Author();
author.name = "Bernardo Soares";
EnhancerTestUtils.checkDirtyTracking( author, "name" );
}
// --- //
@Entity
private static class Author {
@Id
@GeneratedValue
Long id;
@OneToMany( fetch = FetchType.LAZY, mappedBy = "author" )
List<ChildItem> items;
// keep this field after 'items'
String name;
}
@MappedSuperclass
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
@DiscriminatorColumn( name = "type", discriminatorType = DiscriminatorType.STRING )
private static abstract class Item {
@Id
@GeneratedValue
Long id;
@ManyToOne( fetch = FetchType.LAZY )
Author author;
}
@Entity
@DiscriminatorValue( "child" )
private static class ChildItem extends Item {
}
}

View File

@ -0,0 +1,119 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.association;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class ManyToManyAssociationTest {
@Test
public void test() {
Group group = new Group();
Group anotherGroup = new Group();
User user = new User();
User anotherUser = new User();
user.addGroup( group );
user.addGroup( anotherGroup );
anotherUser.addGroup( group );
Assert.assertEquals( 2, group.getUsers().size() );
Assert.assertEquals( 1, anotherGroup.getUsers().size() );
group.resetUsers();
Assert.assertEquals( 1, user.getGroups().size() );
Assert.assertEquals( 0, anotherUser.getGroups().size() );
// Test remove
user.addGroup( group );
anotherUser.addGroup( group );
Assert.assertEquals( 2, group.getUsers().size() );
Assert.assertEquals( 1, anotherGroup.getUsers().size() );
Set<Group> groups = new HashSet<>( user.getGroups() );
groups.remove( group );
user.setGroups( groups );
Assert.assertEquals( 1, group.getUsers().size() );
Assert.assertEquals( 1, anotherGroup.getUsers().size() );
groups.remove( anotherGroup );
user.setGroups( groups );
Assert.assertEquals( 1, group.getUsers().size() );
// This happens (and is expected) because there was no snapshot taken before remove
Assert.assertEquals( 1, anotherGroup.getUsers().size() );
}
// -- //
@Entity
private static class Group {
@Id
Long id;
@Column
String name;
@ManyToMany( mappedBy = "groups" )
Set<User> users = new HashSet<>();
Set<User> getUsers() {
return Collections.unmodifiableSet( users );
}
void resetUsers() {
// this wouldn't trigger association management: users.clear();
users = new HashSet<>();
}
}
@Entity
private static class User {
@Id
Long id;
String password;
@ManyToMany
Set<Group> groups;
void addGroup(Group group) {
Set<Group> groups = this.groups == null ? new HashSet<>() : this.groups;
groups.add( group );
this.groups = groups;
}
Set<Group> getGroups() {
return Collections.unmodifiableSet( groups );
}
void setGroups(Set<Group> groups) {
this.groups = groups;
}
}
}

View File

@ -0,0 +1,121 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.association;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class OneToManyAssociationTest {
@Test
public void test() {
Customer customer = new Customer();
Assert.assertTrue( customer.getInventories().isEmpty() );
CustomerInventory customerInventory = new CustomerInventory();
customerInventory.setCustomer( customer );
Assert.assertEquals( 1, customer.getInventories().size() );
Assert.assertTrue( customer.getInventories().contains( customerInventory ) );
Customer anotherCustomer = new Customer();
Assert.assertTrue( anotherCustomer.getInventories().isEmpty() );
customerInventory.setCustomer( anotherCustomer );
Assert.assertTrue( customer.getInventories().isEmpty() );
Assert.assertEquals( 1, anotherCustomer.getInventories().size() );
Assert.assertSame( customerInventory, anotherCustomer.getInventories().get( 0 ) );
customer.addInventory( customerInventory );
Assert.assertSame( customer, customerInventory.getCustomer() );
Assert.assertTrue( anotherCustomer.getInventories().isEmpty() );
Assert.assertEquals( 1, customer.getInventories().size() );
customer.addInventory( new CustomerInventory() );
Assert.assertEquals( 2, customer.getInventories().size() );
// Test remove
customer.removeInventory( customerInventory );
Assert.assertEquals( 1, customer.getInventories().size() );
// This happens (and is expected) because there was no snapshot taken before remove
Assert.assertNotNull( customerInventory.getCustomer() );
}
// --- //
@Entity
private static class Customer {
@Id
Long id;
String name;
@OneToMany( mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.EAGER )
List<CustomerInventory> customerInventories = new ArrayList<>();
void addInventory(CustomerInventory inventory) {
List<CustomerInventory> list = customerInventories;
list.add( inventory );
customerInventories = list;
}
List<CustomerInventory> getInventories() {
return Collections.unmodifiableList( customerInventories );
}
void removeInventory(CustomerInventory inventory) {
customerInventories.remove( inventory );
}
}
@Entity
private static class CustomerInventory {
@Id
Long id;
@Id
Long custId;
@ManyToOne( cascade = CascadeType.MERGE )
Customer customer;
@ManyToOne( cascade = CascadeType.MERGE )
String vehicle;
Customer getCustomer() {
return customer;
}
void setCustomer(Customer customer) {
this.customer = customer;
}
void setVehicle(String vehicle) {
this.vehicle = vehicle;
}
}
}

View File

@ -0,0 +1,97 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.association;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import java.util.UUID;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class OneToOneAssociationTest {
@Test
public void test() {
User user = new User();
user.setLogin( UUID.randomUUID().toString() );
Customer customer = new Customer();
customer.setUser( user );
Assert.assertEquals( customer, user.getCustomer() );
// check dirty tracking is set automatically with bi-directional association management
EnhancerTestUtils.checkDirtyTracking( user, "login", "customer" );
User anotherUser = new User();
anotherUser.setLogin( UUID.randomUUID().toString() );
customer.setUser( anotherUser );
Assert.assertNull( user.getCustomer() );
Assert.assertEquals( customer, anotherUser.getCustomer() );
user.setCustomer( new Customer() );
Assert.assertEquals( user, user.getCustomer().getUser() );
}
// --- //
@Entity
private static class Customer {
@Id
Long id;
@OneToOne
User user;
User getUser() {
return user;
}
void setUser(User newUser) {
user = newUser;
}
}
@Entity
private static class User {
@Id
Long id;
String login;
String password;
@OneToOne( mappedBy = "user" )
Customer customer;
void setLogin(String login) {
this.login = login;
}
Customer getCustomer() {
return customer;
}
void setCustomer(Customer customer) {
this.customer = customer;
}
}
}

View File

@ -0,0 +1,279 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class BasicEnhancementTest {
@Test
public void basicManagedTest() {
SimpleEntity entity = new SimpleEntity();
// Call the new ManagedEntity methods
assertTyping( ManagedEntity.class, entity );
ManagedEntity managedEntity = (ManagedEntity) entity;
assertSame( entity, managedEntity.$$_hibernate_getEntityInstance() );
assertNull( managedEntity.$$_hibernate_getEntityEntry() );
managedEntity.$$_hibernate_setEntityEntry( EnhancerTestUtils.makeEntityEntry() );
assertNotNull( managedEntity.$$_hibernate_getEntityEntry() );
managedEntity.$$_hibernate_setEntityEntry( null );
assertNull( managedEntity.$$_hibernate_getEntityEntry() );
managedEntity.$$_hibernate_setNextManagedEntity( managedEntity );
managedEntity.$$_hibernate_setPreviousManagedEntity( managedEntity );
assertSame( managedEntity, managedEntity.$$_hibernate_getNextManagedEntity() );
assertSame( managedEntity, managedEntity.$$_hibernate_getPreviousManagedEntity() );
}
@Test
public void basicInterceptableTest() {
SimpleEntity entity = new SimpleEntity();
assertTyping( PersistentAttributeInterceptable.class, entity );
PersistentAttributeInterceptable interceptableEntity = (PersistentAttributeInterceptable) entity;
assertNull( interceptableEntity.$$_hibernate_getInterceptor() );
interceptableEntity.$$_hibernate_setInterceptor( new ObjectAttributeMarkerInterceptor() );
assertNotNull( interceptableEntity.$$_hibernate_getInterceptor() );
assertNull( EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" ) );
entity.setAnObject( new Object() );
assertSame( ObjectAttributeMarkerInterceptor.WRITE_MARKER, EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" ) );
assertSame( ObjectAttributeMarkerInterceptor.READ_MARKER, entity.getAnObject() );
entity.setAnObject( null );
assertSame( ObjectAttributeMarkerInterceptor.WRITE_MARKER, EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" ) );
}
@Test
public void basicExtendedEnhancementTest() {
// test uses ObjectAttributeMarkerInterceptor to ensure that field access is routed through enhanced methods
SimpleEntity entity = new SimpleEntity();
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( new ObjectAttributeMarkerInterceptor() );
Object decoy = new Object();
entity.anUnspecifiedObject = decoy;
Object gotByReflection = EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" );
assertNotSame( decoy, gotByReflection );
assertSame( ObjectAttributeMarkerInterceptor.WRITE_MARKER, gotByReflection );
Object entityObject = entity.anUnspecifiedObject;
assertNotSame( decoy, entityObject );
assertSame( ObjectAttributeMarkerInterceptor.READ_MARKER, entityObject );
// do some more calls on the various types, without the interceptor
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( null );
entity.id = 1234567890L;
Assert.assertEquals( 1234567890L, (long) entity.getId() );
entity.name = "Entity Name";
assertSame( "Entity Name", entity.name );
entity.active = true;
assertTrue( entity.getActive() );
entity.someStrings = Arrays.asList( "A", "B", "C", "D" );
assertArrayEquals( new String[]{"A", "B", "C", "D"}, entity.someStrings.toArray() );
}
// --- //
public static class ObjectAttributeMarkerInterceptor implements PersistentAttributeInterceptor {
public static final Object READ_MARKER = new Object();
public static final Object WRITE_MARKER = new Object();
@Override
public boolean readBoolean(Object obj, String name, boolean oldValue) {
return oldValue;
}
@Override
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) {
return newValue;
}
@Override
public byte readByte(Object obj, String name, byte oldValue) {
return oldValue;
}
@Override
public byte writeByte(Object obj, String name, byte oldValue, byte newValue) {
return newValue;
}
@Override
public char readChar(Object obj, String name, char oldValue) {
return oldValue;
}
@Override
public char writeChar(Object obj, String name, char oldValue, char newValue) {
return newValue;
}
@Override
public short readShort(Object obj, String name, short oldValue) {
return oldValue;
}
@Override
public short writeShort(Object obj, String name, short oldValue, short newValue) {
return newValue;
}
@Override
public int readInt(Object obj, String name, int oldValue) {
return oldValue;
}
@Override
public int writeInt(Object obj, String name, int oldValue, int newValue) {
return newValue;
}
@Override
public float readFloat(Object obj, String name, float oldValue) {
return oldValue;
}
@Override
public float writeFloat(Object obj, String name, float oldValue, float newValue) {
return newValue;
}
@Override
public double readDouble(Object obj, String name, double oldValue) {
return oldValue;
}
@Override
public double writeDouble(Object obj, String name, double oldValue, double newValue) {
return newValue;
}
@Override
public long readLong(Object obj, String name, long oldValue) {
return oldValue;
}
@Override
public long writeLong(Object obj, String name, long oldValue, long newValue) {
return newValue;
}
@Override
public Object readObject(Object obj, String name, Object oldValue) {
return READ_MARKER;
}
@Override
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
return WRITE_MARKER;
}
@Override
public Set<String> getInitializedLazyAttributeNames() {
return null;
}
@Override
public void attributeInitialized(String name) {
}
}
// --- //
@Entity
private static class SimpleEntity {
Object anUnspecifiedObject;
@Id
Long id;
String name;
Boolean active;
List<String> someStrings;
Long getId() {
return id;
}
void setId(Long id) {
this.id = id;
}
String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
Object getAnObject() {
return anUnspecifiedObject;
}
void setAnObject(Object providedObject) {
this.anUnspecifiedObject = providedObject;
}
List<String> getSomeStrings() {
return Collections.unmodifiableList( someStrings );
}
void setSomeStrings(List<String> someStrings) {
this.someStrings = someStrings;
}
}
}

View File

@ -0,0 +1,124 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class BasicSessionTest extends BaseCoreFunctionalTestCase {
@Test
public void test() {
buildSessionFactory( configuration -> configuration.addAnnotatedClass( MyEntity.class ) );
doInHibernate( this::sessionFactory, s -> {
s.save( new MyEntity( 1L ) );
s.save( new MyEntity( 2L ) );
} );
MyEntity[] entities = new MyEntity[2];
doInHibernate( this::sessionFactory, s -> {
entities[0] = s.get( MyEntity.class, 1L );
entities[1] = s.get( MyEntity.class, 2L );
assertNotNull( entities[0].$$_hibernate_getEntityInstance() );
assertSame( entities[0], entities[0].$$_hibernate_getEntityInstance() );
assertNotNull( entities[0].$$_hibernate_getEntityEntry() );
assertNull( entities[0].$$_hibernate_getPreviousManagedEntity() );
assertNotNull( entities[0].$$_hibernate_getNextManagedEntity() );
assertNotNull( entities[1].$$_hibernate_getEntityInstance() );
assertSame( entities[1], entities[1].$$_hibernate_getEntityInstance() );
assertNotNull( entities[1].$$_hibernate_getEntityEntry() );
assertNotNull( entities[1].$$_hibernate_getPreviousManagedEntity() );
assertNull( entities[1].$$_hibernate_getNextManagedEntity() );
s.createQuery( "delete MyEntity" ).executeUpdate();
} );
assertNull( entities[0].$$_hibernate_getEntityEntry() );
assertNull( entities[1].$$_hibernate_getEntityEntry() );
}
// --- //
@Entity( name = "MyEntity" )
@Table( name = "MY_ENTITY" )
private static class MyEntity implements ManagedEntity {
@Id
Long id;
@Transient
private transient EntityEntry entityEntry;
@Transient
private transient ManagedEntity previous;
@Transient
private transient ManagedEntity next;
MyEntity() {
}
MyEntity(Long id) {
this.id = id;
}
@Override
public Object $$_hibernate_getEntityInstance() {
return this;
}
@Override
public EntityEntry $$_hibernate_getEntityEntry() {
return entityEntry;
}
@Override
public void $$_hibernate_setEntityEntry(EntityEntry entityEntry) {
this.entityEntry = entityEntry;
}
@Override
public ManagedEntity $$_hibernate_getNextManagedEntity() {
return next;
}
@Override
public void $$_hibernate_setNextManagedEntity(ManagedEntity next) {
this.next = next;
}
@Override
public ManagedEntity $$_hibernate_getPreviousManagedEntity() {
return previous;
}
@Override
public void $$_hibernate_setPreviousManagedEntity(ManagedEntity previous) {
this.previous = previous;
}
}
}

View File

@ -0,0 +1,75 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;
import javax.persistence.Table;
import java.io.Serializable;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-9529" )
@RunWith( BytecodeEnhancerRunner.class )
public class CrossEnhancementTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class, Child.class, ChildKey.class};
}
@Test
public void test() {
buildSessionFactory();
}
// --- //
@Entity
@Table( name = "PARENT" )
private static class Parent {
@Id
String id;
}
@Embeddable
private static class ChildKey implements Serializable {
String parent;
String type;
}
@Entity
@Table( name = "CHILD" )
private static class Child {
@EmbeddedId
ChildKey id;
@MapsId( "parent" )
@ManyToOne
Parent parent;
public String getfieldOnChildKeyParent() {
// Note that there are two GETFIELD ops here, one on the field 'id' that should be enhanced and another
// on the field 'parent' that may be or not (depending if 'extended enhancement' is enabled)
// Either way, the field 'parent' on ChildKey should not be confused with the field 'parent' on Child
return id.parent;
}
}
}

View File

@ -0,0 +1,84 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import java.util.UUID;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.getFieldByReflection;
import static org.junit.Assert.assertEquals;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class ExtendedAssociationManagementTest {
@Test
public void test() {
User user = new User();
user.login = UUID.randomUUID().toString();
Customer customer = new Customer();
customer.user = user;
assertEquals( customer, getFieldByReflection( user, "customer" ) );
// check dirty tracking is set automatically with bi-directional association management
EnhancerTestUtils.checkDirtyTracking( user, "login", "customer" );
User anotherUser = new User();
anotherUser.login = UUID.randomUUID().toString();
customer.user = anotherUser;
Assert.assertNull( user.customer );
assertEquals( customer, getFieldByReflection( anotherUser, "customer" ) );
user.customer = new Customer();
assertEquals( user, user.customer.user );
}
// --- //
@Entity
private static class Customer {
@Id
Long id;
String firstName;
String lastName;
@OneToOne( fetch = FetchType.LAZY )
User user;
}
@Entity
private static class User {
@Id
Long id;
String login;
String password;
@OneToOne( mappedBy = "user", fetch = FetchType.LAZY )
Customer customer;
}
}

View File

@ -0,0 +1,126 @@
package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Version;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.clearDirtyTracking;
/**
* @author Luis Barreiro
* @author Craig Andrews
*/
@TestForIssue( jiraKey = "HHH-11284" )
@RunWith( BytecodeEnhancerRunner.class )
@CustomEnhancementContext( {EnhancerTestContext.class, InheritedTest.EagerEnhancementContext.class} )
public class InheritedTest {
@Test
public void test() {
Employee charles = new Employee( "Charles", "Engineer" );
charles.setOca( 1002 );
// Check that both types of class attributes are being dirty tracked
checkDirtyTracking( charles, "title", "oca" );
clearDirtyTracking( charles );
// Let's give charles a promotion, this time using method references
charles.setOca( 99 );
charles.setTitle( "Manager" );
checkDirtyTracking( charles, "title", "oca" );
Contractor bob = new Contractor( "Bob", 100 );
bob.setOca( 1003 );
// Check that both types of class attributes are being dirty tracked
checkDirtyTracking( bob, "rate", "oca" );
clearDirtyTracking( bob );
// Let's give bob a rate increase, this time using method references
bob.setOca( 88 );
bob.setRate( 200 );
checkDirtyTracking( bob, "rate", "oca" );
}
// --- //
@Entity
private static abstract class Person {
@Id
String name;
@Version
long oca;
Person() {
}
Person(String name) {
this();
this.name = name;
}
void setOca(long l) {
this.oca = l;
}
}
@Entity
private static class Employee extends Person {
String title;
Employee() {
}
Employee(String name, String title) {
super( name );
this.title = title;
}
void setTitle(String title) {
this.title = title;
}
}
@Entity
private static class Contractor extends Person {
Integer rate;
Contractor() {
}
Contractor(String name, Integer rate) {
super( name );
this.rate = rate;
}
void setRate(Integer rate) {
this.rate = rate;
}
}
// --- //
public static class EagerEnhancementContext extends DefaultEnhancementContext {
@Override
public boolean hasLazyLoadableAttributes(UnloadedClass classDescriptor) {
// HHH-10981 - Without lazy loading, the generation of getters and setters has a different code path
return false;
}
}
}

View File

@ -0,0 +1,94 @@
package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.clearDirtyTracking;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-10646" )
@RunWith( BytecodeEnhancerRunner.class )
@CustomEnhancementContext( {EnhancerTestContext.class, MappedSuperclassTest.EagerEnhancementContext.class} )
public class MappedSuperclassTest {
@Test
public void test() {
Employee charles = new Employee( "Charles", "Engineer" );
charles.setOca( 1002 );
// Check that both types of class attributes are being dirty tracked
checkDirtyTracking( charles, "title", "oca" );
clearDirtyTracking( charles );
// Let's give charles a promotion, this time using method references
charles.setOca( 99 );
charles.setTitle( "Manager" );
checkDirtyTracking( charles, "title", "oca" );
}
// --- //
@MappedSuperclass
private static class Person {
@Id
String name;
@Version
Long oca;
Person(String name) {
this.name = name;
}
Person() {
}
void setOca(long l) {
this.oca = l;
}
}
@Entity
private static class Employee extends Person {
String title;
Employee(String name, String title) {
super( name );
this.title = title;
}
Employee() {
}
void setTitle(String title) {
this.title = title;
}
}
// --- //
public static class EagerEnhancementContext extends DefaultEnhancementContext {
@Override
public boolean hasLazyLoadableAttributes(UnloadedClass classDescriptor) {
// HHH-10981 - Without lazy loading, the generation of getters and setters has a different code path
return false;
}
}
}

View File

@ -0,0 +1,158 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.cascade;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-10252" )
@RunWith( BytecodeEnhancerRunner.class )
public class CascadeDeleteTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{Parent.class, Child.class};
}
@Before
public void prepare() {
buildSessionFactory();
// Create a Parent with one Child
doInHibernate( this::sessionFactory, s -> {
Parent p = new Parent();
p.setName( "PARENT" );
p.setLazy( "LAZY" );
p.makeChild();
s.persist( p );
}
);
}
@Test
public void test() {
// Delete the Parent
doInHibernate( this::sessionFactory, s -> {
Parent loadedParent = (Parent) s.createQuery( "SELECT p FROM Parent p WHERE name=:name" )
.setParameter( "name", "PARENT" )
.uniqueResult();
s.delete( loadedParent );
} );
// If the lazy relation is not fetch on cascade there is a constraint violation on commit
}
// --- //
@Entity( name = "Parent" )
@Table( name = "PARENT" )
public static class Parent {
Long id;
String name;
List<Child> children = new ArrayList<>();
String lazy;
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long getId() {
return id;
}
void setId(Long id) {
this.id = id;
}
@OneToMany( mappedBy = "parent", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, fetch = FetchType.LAZY )
List<Child> getChildren() {
return Collections.unmodifiableList( children );
}
void setChildren(List<Child> children) {
this.children = children;
}
String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
@Basic( fetch = FetchType.LAZY )
String getLazy() {
return lazy;
}
void setLazy(String lazy) {
this.lazy = lazy;
}
void makeChild() {
Child c = new Child();
c.setParent( this );
children.add( c );
}
}
@Entity
@Table( name = "CHILD" )
private static class Child {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@ManyToOne( optional = false )
@JoinColumn( name = "parent_id" )
Parent parent;
Long getId() {
return id;
}
void setId(Long id) {
this.id = id;
}
Parent getParent() {
return parent;
}
void setParent(Parent parent) {
this.parent = parent;
}
}
}

View File

@ -0,0 +1,120 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.cascade;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-10252" )
@RunWith( BytecodeEnhancerRunner.class )
public class CascadeWithFkConstraintTest extends BaseCoreFunctionalTestCase {
private String garageId, car1Id, car2Id;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Garage.class, Car.class};
}
@Before
public void prepare() {
buildSessionFactory();
// Create garage, add 2 cars to garage
doInJPA( this::sessionFactory, em -> {
Garage garage = new Garage();
Car car1 = new Car();
Car car2 = new Car();
garage.insert( car1 );
garage.insert( car2 );
em.persist( garage );
em.persist( car1 );
em.persist( car2 );
garageId = garage.id;
car1Id = car1.id;
car2Id = car2.id;
} );
}
@Test
public void test() {
// Remove garage
doInJPA( this::sessionFactory, em -> {
Garage toRemoveGarage = em.find( Garage.class, garageId );
em.remove( toRemoveGarage );
} );
// Check if there is no garage but cars are still present
doInJPA( this::sessionFactory, em -> {
Garage foundGarage = em.find( Garage.class, garageId );
Assert.assertNull( foundGarage );
Car foundCar1 = em.find( Car.class, car1Id );
Assert.assertEquals( car1Id, foundCar1.id );
Car foundCar2 = em.find( Car.class, car2Id );
Assert.assertEquals( car2Id, foundCar2.id );
} );
}
// --- //
@Entity
@Table( name = "GARAGE" )
private static class Garage {
@Id
String id;
@OneToMany
@JoinColumn( name = "GARAGE_ID" )
Set<Car> cars = new HashSet<>();
Garage() {
id = UUID.randomUUID().toString();
}
void insert(Car aCar) {
cars.add( aCar );
}
}
@Entity
@Table( name = "CAR" )
public static class Car {
@Id
String id;
Car() {
id = UUID.randomUUID().toString();
}
}
}

View File

@ -0,0 +1,61 @@
package org.hibernate.test.bytecode.enhancement.detached;
import org.hibernate.SessionFactory;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.transaction.TransactionUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import static org.junit.Assert.assertNotNull;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-11426" )
@RunWith( BytecodeEnhancerRunner.class )
public class DetachedGetIdentifierTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{SimpleEntity.class};
}
@Test
public void test() {
buildSessionFactory();
SimpleEntity[] entities = new SimpleEntity[2];
entities[0] = new SimpleEntity();
entities[0].name = "test";
TransactionUtil.doInJPA( this::sessionFactory, em -> {
entities[1] = em.merge( entities[0] );
assertNotNull( em.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier( entities[1] ) );
} );
// Call as detached entity
try ( SessionFactory sessionFactory = sessionFactory() ) {
assertNotNull( sessionFactory.getPersistenceUnitUtil().getIdentifier( entities[1] ) );
}
}
// --- //
@Entity
@Table( name = "SIMPLE_ENTITY" )
private static class SimpleEntity {
@Id
@GeneratedValue
Long id;
String name;
}
}

View File

@ -0,0 +1,88 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.dirty;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-11293" )
@RunWith( BytecodeEnhancerRunner.class )
public class DirtyTrackingCollectionTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{StringsEntity.class};
}
@Before
public void prepare() {
buildSessionFactory();
doInJPA( this::sessionFactory, em -> {
StringsEntity entity = new StringsEntity();
entity.id = 1L;
entity.someStrings = new ArrayList<>( Arrays.asList( "a", "b", "c" ) );
em.persist( entity );
} );
}
@Test
public void test() {
doInJPA( this::sessionFactory, entityManager -> {
StringsEntity entity = entityManager.find( StringsEntity.class, 1L );
entity.someStrings.clear();
} );
doInJPA( this::sessionFactory, entityManager -> {
StringsEntity entity = entityManager.find( StringsEntity.class, 1L );
assertEquals( 0, entity.someStrings.size() );
entity.someStrings.add( "d" );
} );
doInJPA( this::sessionFactory, entityManager -> {
StringsEntity entity = entityManager.find( StringsEntity.class, 1L );
assertEquals( 1, entity.someStrings.size() );
entity.someStrings = new ArrayList<>();
} );
doInJPA( this::sessionFactory, entityManager -> {
StringsEntity entity = entityManager.find( StringsEntity.class, 1L );
assertEquals( 0, entity.someStrings.size() );
} );
}
// --- //
@Entity
@Table( name = "STRINGS_ENTITY" )
private static class StringsEntity {
@Id
Long id;
@ElementCollection
List<String> someStrings;
}
}

View File

@ -0,0 +1,144 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.dirty;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class DirtyTrackingTest {
@Test
public void test() {
SimpleEntity entity = new SimpleEntity();
EnhancerTestUtils.clearDirtyTracking( entity );
// Basic single field
Long number = entity.getSomeNumber();
EnhancerTestUtils.checkDirtyTracking( entity );
entity.setSomeNumber( number + 1L );
EnhancerTestUtils.checkDirtyTracking( entity, "someNumber" );
EnhancerTestUtils.clearDirtyTracking( entity );
entity.setSomeNumber( entity.getSomeNumber() );
EnhancerTestUtils.checkDirtyTracking( entity );
// Basic multi-field (Id properties are not flagged as dirty)
entity.id = 2L;
entity.active = !entity.active;
entity.someNumber = 193L;
EnhancerTestUtils.checkDirtyTracking( entity, "active", "someNumber" );
EnhancerTestUtils.clearDirtyTracking( entity );
// Setting the same value should not make it dirty
entity.someNumber = 193L;
EnhancerTestUtils.checkDirtyTracking( entity );
// Collection
List<String> stringList = new ArrayList<>();
stringList.add( "FooBar" );
entity.someStrings = stringList;
EnhancerTestUtils.checkDirtyTracking( entity, "someStrings" );
EnhancerTestUtils.clearDirtyTracking( entity );
stringList.add( "BarFoo" );
EnhancerTestUtils.checkDirtyTracking( entity, "someStrings" );
EnhancerTestUtils.clearDirtyTracking( entity );
// Association: this should not set the entity to dirty
Set<Integer> intSet = new HashSet<>();
intSet.add( 42 );
entity.someInts = intSet;
EnhancerTestUtils.checkDirtyTracking( entity );
// testing composite object
Address address = new Address();
entity.address = address;
address.city = "Arendal";
EnhancerTestUtils.checkDirtyTracking( entity, "address" );
EnhancerTestUtils.clearDirtyTracking( entity );
// make sure that new composite instances are cleared
Address address2 = new Address();
entity.address = address2;
address.street1 = "Heggedalveien";
EnhancerTestUtils.checkDirtyTracking( entity, "address" );
Country country = new Country();
address2.country = country;
country.name = "Norway";
EnhancerTestUtils.checkDirtyTracking( entity, "address", "address.country" );
address.country = null;
entity.address = null;
}
// --- //
@Embeddable
private static class Address {
@Embedded
Country country;
String street1;
String street2;
String city;
String state;
String zip;
String phone;
}
@Embeddable
private static class Country {
String name;
}
@Entity
private static class SimpleEntity {
@Id
Long id;
String name;
Boolean active = Boolean.FALSE;
Long someNumber = 0L;
List<String> someStrings;
@OneToMany
Set<Integer> someInts;
@Embedded
Address address;
@Embedded
Address address2;
public Long getSomeNumber() {
return someNumber;
}
public void setSomeNumber(Long someNumber) {
this.someNumber = someNumber;
}
}
}

View File

@ -0,0 +1,104 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.eviction;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
@RunWith( BytecodeEnhancerRunner.class )
public class EvictionTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class};
}
@Before
public void prepare() {
buildSessionFactory();
// Create a Parent
doInHibernate( this::sessionFactory, s -> {
Parent p = new Parent();
p.name = "PARENT";
s.persist( p );
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
// Delete the Parent
Parent loadedParent = (Parent) s.createQuery( "SELECT p FROM Parent p WHERE name=:name" )
.setParameter( "name", "PARENT" )
.uniqueResult();
assertTyping( ManagedEntity.class, loadedParent );
ManagedEntity managedParent = (ManagedEntity) loadedParent;
// before eviction
assertNotNull( managedParent.$$_hibernate_getEntityInstance() );
assertNotNull( managedParent.$$_hibernate_getEntityEntry() );
assertNull( managedParent.$$_hibernate_getPreviousManagedEntity() );
assertNull( managedParent.$$_hibernate_getNextManagedEntity() );
assertTrue( s.contains( managedParent ) );
s.evict( managedParent );
// after eviction
assertFalse( s.contains( managedParent ) );
assertNotNull( managedParent.$$_hibernate_getEntityInstance() );
assertNull( managedParent.$$_hibernate_getEntityEntry() );
assertNull( managedParent.$$_hibernate_getPreviousManagedEntity() );
assertNull( managedParent.$$_hibernate_getNextManagedEntity() );
// evict again
s.evict( managedParent );
assertFalse( s.contains( managedParent ) );
assertNotNull( managedParent.$$_hibernate_getEntityInstance() );
assertNull( managedParent.$$_hibernate_getEntityEntry() );
assertNull( managedParent.$$_hibernate_getPreviousManagedEntity() );
assertNull( managedParent.$$_hibernate_getNextManagedEntity() );
s.delete( managedParent );
} );
}
// --- //
@Entity( name = "Parent" )
@Table( name = "PARENT" )
private static class Parent {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
String name;
}
}

View File

@ -6,64 +6,61 @@
*/
package org.hibernate.test.bytecode.enhancement.javassist;
import javassist.CtClass;
import org.hibernate.bytecode.enhance.internal.javassist.EnhancerImpl;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import javassist.CtClass;
import org.hibernate.bytecode.enhance.internal.javassist.EnhancerImpl;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
/**
* @author Vlad Mihalcea
*/
public class EnhancerFileNotFoundTest extends BaseUnitTestCase {
public class EnhancerFileNotFoundTest {
public static class Enhancer extends EnhancerImpl {
@Test
@TestForIssue( jiraKey = "HHH-11307" )
public void test() throws Exception {
Enhancer enhancer = new Enhancer( new DefaultEnhancementContext() );
try {
Class<?> clazz = getClass().getClassLoader().loadClass( Hidden.class.getName() );
String resourceName = clazz.getName().replace( '.', '/' ) + ".class";
URL url = getClass().getClassLoader().getResource( resourceName );
if ( url != null ) {
Files.delete( Paths.get( url.toURI() ) );
enhancer.loadCtClassFromClass( clazz );
}
fail( "Should throw FileNotFoundException!" );
} catch ( Exception expected ) {
assertSame( FileNotFoundException.class, expected.getCause().getClass() );
}
}
public Enhancer(EnhancementContext enhancementContext) {
super( enhancementContext );
}
// --- //
@Override
public CtClass loadCtClassFromClass(Class<?> aClass) {
return super.loadCtClassFromClass( aClass );
}
}
private static class Enhancer extends EnhancerImpl {
@Test
@TestForIssue(jiraKey = "HHH-11307")
public void test()
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
EnhancementContext enhancementContextMock = mock( EnhancementContext.class );
public Enhancer(EnhancementContext enhancementContext) {
super( enhancementContext );
}
Enhancer enhancer = new Enhancer( enhancementContextMock );
try {
Class<?> clazz = Hidden.class;
String resourceName = Hidden.class.getName().replace( '.', '/' ) + ".class";
URL url = getClass().getClassLoader().getResource( resourceName );
Files.delete( Paths.get(url.toURI()) );
enhancer.loadCtClassFromClass( clazz );
fail("Should throw FileNotFoundException!");
}
catch ( Exception expected ) {
assertEquals( FileNotFoundException.class, expected.getCause().getClass() );
}
}
@Override
// change visibility protected -> public
public CtClass loadCtClassFromClass(Class<?> aClass) {
return super.loadCtClassFromClass( aClass );
}
}
private static class Hidden {
}
// --- //
private static class Hidden {
}
}

View File

@ -0,0 +1,221 @@
package org.hibernate.test.bytecode.enhancement.join;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import java.util.List;
import static org.hibernate.Hibernate.isInitialized;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@TestForIssue( jiraKey = "HHH-3949" )
@RunWith( BytecodeEnhancerRunner.class )
public class HHH3949Test extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Person.class, Vehicle.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
// see HHH-3949 for further details ^^^^^
} );
doInHibernate( this::sessionFactory, s -> {
// it is important that the data associations remain as follows:
// * Johnny <-> Volkswagen Golf
// * Ricky <-> Subaru Impreza
// * Rosy -> none
// * none <- Renault Truck
//
// see #shouldHaveVehicle and #shouldHaveDriver
Person person1 = new Person( "Johnny" );
Person person2 = new Person( "Ricky" );
Person person3 = new Person( "Rosy" );
s.save( person1 );
s.save( person2 );
s.save( person3 );
Vehicle vehicle1 = new Vehicle( "Volkswagen Golf" );
vehicle1.setDriver( person1 );
s.save( vehicle1 );
Vehicle vehicle2 = new Vehicle( "Subaru Impreza" );
vehicle2.setDriver( person2 );
person2.setVehicle( vehicle2 );
s.save( vehicle2 );
Vehicle vehicle3 = new Vehicle( "Renault Truck" );
s.save( vehicle3 );
} );
}
@Test
public void test1() {
// verify the work around query
performQueryAndVerifyPersonResults( "from Person p fetch all properties left join fetch p.vehicle" );
performQueryAndVerifyPersonResults( "from Person p left join fetch p.vehicle" );
}
@Test
public void test2() {
performQueryAndVerifyVehicleResults( "from Vehicle v fetch all properties left join fetch v.driver" );
performQueryAndVerifyVehicleResults( "from Vehicle v left join fetch v.driver" );
}
@Test
@SuppressWarnings( "unchecked" )
public void test3() {
doInHibernate( this::sessionFactory, s -> {
List<Person> persons = (List<Person>) s.createCriteria( Person.class ).setFetchMode( "vehicle", FetchMode.JOIN ).list();
for ( Person person : persons ) {
if ( shouldHaveVehicle( person ) ) {
assertNotNull( person.getVehicle() );
assertNotNull( person.getVehicle().getDriver() );
}
}
} );
}
@Test
@SuppressWarnings( "unchecked" )
public void test4() {
List<Vehicle> vehicles;
try ( Session s = openSession() ) {
vehicles = (List<Vehicle>) s.createCriteria( Vehicle.class ).setFetchMode( "driver", FetchMode.JOIN ).list();
}
for ( Vehicle vehicle : vehicles ) {
if ( shouldHaveDriver( vehicle ) ) {
assertNotNull( vehicle.getDriver() );
assertNotNull( vehicle.getDriver().getVehicle() );
}
}
}
// --- //
@SuppressWarnings( "unchecked" )
private void performQueryAndVerifyPersonResults(String query) {
List<Person> persons;
try ( Session s = openSession() ) {
persons = (List<Person>) s.createQuery( query ).list();
}
for ( Person person : persons ) {
assertTrue( isInitialized( person ) );
if ( shouldHaveVehicle( person ) ) {
assertNotNull( person.getVehicle() );
assertTrue( isInitialized( person.getVehicle() ) );
assertNotNull( person.getVehicle().getDriver() );
}
}
}
@SuppressWarnings( "unchecked" )
private void performQueryAndVerifyVehicleResults(String query) {
List<Vehicle> vehicles;
try ( Session s = openSession() ) {
vehicles = (List<Vehicle>) s.createQuery( query ).list();
}
for ( Vehicle vehicle : vehicles ) {
if ( shouldHaveDriver( vehicle ) ) {
assertNotNull( vehicle.getDriver() );
assertNotNull( vehicle.getDriver().getVehicle() );
}
}
}
private boolean shouldHaveVehicle(Person person) {
return "Johnny".equals( person.name ) || "Ricky".equals( person.name );
}
private boolean shouldHaveDriver(Vehicle vehicle) {
return "Volkswagen Golf".equals( vehicle.name ) || "Subaru Impreza".equals( vehicle.name );
}
// --- //
@Entity( name = "Person" )
@Table( name = "PERSON" )
private static class Person {
@Id
@GeneratedValue
Long id;
String name;
@OneToOne( optional = true, mappedBy = "driver", fetch = FetchType.LAZY )
@LazyToOne( LazyToOneOption.NO_PROXY )
Vehicle vehicle;
Person() {
}
Person(String name) {
this.name = name;
}
Vehicle getVehicle() {
return vehicle;
}
void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
}
@Entity( name = "Vehicle" )
@Table( name = "VEHICLE" )
private static class Vehicle {
@Id
@GeneratedValue
Long id;
String name;
@OneToOne( optional = true, fetch = FetchType.LAZY )
Person driver;
Vehicle() {
}
Vehicle(String name) {
this.name = name;
}
Person getDriver() {
return driver;
}
void setDriver(Person driver) {
this.driver = driver;
}
}
}

View File

@ -0,0 +1,96 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy.HHH_10708;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
@TestForIssue( jiraKey = "HHH-10708" )
@RunWith( BytecodeEnhancerRunner.class )
public class UnexpectedDeleteTest1 extends BaseCoreFunctionalTestCase {
private long fooId;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[]{Foo.class, Bar.class};
}
@Before
public void prepare() {
buildSessionFactory();
doInHibernate( this::sessionFactory, s -> {
Bar bar1 = new Bar();
Bar bar2 = new Bar();
Foo foo = new Foo();
s.save( bar1 );
s.save( bar2 );
s.save( foo );
bar1.foo = foo;
bar2.foo = foo;
fooId = foo.id;
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
Foo foo = s.get( Foo.class, fooId );
// accessing the collection results in an exception
foo.bars.size();
} );
}
// --- //
@Entity
@Table( name = "BAR" )
private static class Bar {
@Id
@GeneratedValue
Long id;
@ManyToOne
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
Foo foo;
}
@Entity
@Table( name = "FOO" )
private static class Foo {
@Id
@GeneratedValue
Long id;
@OneToMany( orphanRemoval = true, mappedBy = "foo", targetEntity = Bar.class )
@Cascade( CascadeType.ALL )
Set<Bar> bars = new HashSet<>();
}
}

View File

@ -0,0 +1,95 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy.HHH_10708;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
@TestForIssue( jiraKey = "HHH-10708" )
@RunWith( BytecodeEnhancerRunner.class )
public class UnexpectedDeleteTest2 extends BaseCoreFunctionalTestCase {
private Bar myBar;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[]{Foo.class, Bar.class};
}
@Before
public void prepare() {
buildSessionFactory();
doInHibernate( this::sessionFactory, s -> {
Bar bar = new Bar();
Foo foo1 = new Foo();
Foo foo2 = new Foo();
s.save( bar );
s.save( foo1 );
s.save( foo2 );
bar.foos.add( foo1 );
bar.foos.add( foo2 );
myBar = bar;
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
s.refresh( myBar );
Assert.assertFalse( myBar.foos.isEmpty() );
// The issue is that currently, for some unknown reason, foos are deleted on flush
} );
doInHibernate( this::sessionFactory, s -> {
Bar bar = s.get( Bar.class, myBar.id );
Assert.assertFalse( bar.foos.isEmpty() );
} );
}
// --- //
@Entity
@Table( name = "BAR" )
private static class Bar {
@Id
@GeneratedValue
Long id;
@ManyToMany( fetch = FetchType.LAZY, targetEntity = Foo.class )
Set<Foo> foos = new HashSet<>();
}
@Entity
@Table( name = "FOO" )
private static class Foo {
@Id
@GeneratedValue
Long id;
}
}

View File

@ -0,0 +1,136 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy.HHH_10708;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
@TestForIssue( jiraKey = "HHH-10708" )
@RunWith( BytecodeEnhancerRunner.class )
public class UnexpectedDeleteTest3 extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[]{Parent.class, Child.class};
}
@Before
public void prepare() {
buildSessionFactory();
doInHibernate( this::sessionFactory, s -> {
Child child = new Child();
child.setId( 2L );
s.save( child );
Parent parent = new Parent();
parent.setId( 1L );
parent.setNames( Collections.singleton( "name" ) );
parent.addChild( child );
s.save( parent );
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
Parent parent = s.get( Parent.class, 1L );
Child child = new Child();
child.setId( 1L );
s.save( child );
parent.addChild( child );
// We need to leave at least one attribute unfetchd
//parent.getNames().size();
s.save( parent );
} );
doInHibernate( this::sessionFactory, s -> {
Parent application = s.get( Parent.class, 1L );
Assert.assertEquals( "Loaded Children collection has unexpected size", 2, application.getChildren().size() );
} );
}
// --- //
@Entity
@Table( name = "CHILD" )
private static class Child {
Long id;
@Id
@Column( name = "id", unique = true, nullable = false )
Long getId() {
return id;
}
void setId(Long id) {
this.id = id;
}
}
@Entity
@Table( name = "PARENT" )
private static class Parent {
Long id;
Set<String> names;
Set<Child> children;
@Id
@Column( name = "id", unique = true, nullable = false )
Long getId() {
return id;
}
void setId(Long id) {
this.id = id;
}
@ElementCollection
Set<String> getNames() {
return Collections.unmodifiableSet( names );
}
void setNames(Set<String> secrets) {
this.names = secrets;
}
@ManyToMany( fetch = FetchType.LAZY, targetEntity = Child.class )
Set<Child> getChildren() {
return Collections.unmodifiableSet( children );
}
void addChild(Child child) {
if (children == null) {
children = new HashSet<>();
}
children.add( child );
}
}
}

View File

@ -0,0 +1,96 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Persister;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
@TestForIssue( jiraKey = "HHH-9937")
@RunWith( BytecodeEnhancerRunner.class )
public class LazyBasicFieldNotInitializedTest extends BaseCoreFunctionalTestCase {
private Long entityId;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{TestEntity.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
} );
doInHibernate( this::sessionFactory, s -> {
TestEntity entity = new TestEntity();
entity.description = "desc";
s.persist( entity );
entityId = entity.id;
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
TestEntity entity = s.get( TestEntity.class, entityId );
Assert.assertFalse( Hibernate.isPropertyInitialized( entity, "description" ) );
EntityPersister entityPersister = sessionFactory().getMetamodel().entityPersister( TestEntity.class );
boolean[] propertyLaziness = entityPersister.getPropertyLaziness();
assertEquals( 1, propertyLaziness.length );
assertTrue( propertyLaziness[0] );
// Make sure NonIdentifierAttribute#isLazy is consistent (HHH-10551)
NonIdentifierAttribute[] properties = entityPersister.getEntityMetamodel().getProperties();
assertEquals( 1, properties.length );
assertTrue( properties[0].isLazy() );
} );
}
// --- //
@Entity
@Table( name = "TEST_ENTITY" )
private static class TestEntity {
@Id
@GeneratedValue
Long id;
@Basic( fetch = FetchType.LAZY )
String description;
}
}

View File

@ -0,0 +1,142 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import javax.persistence.Query;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertFalse;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-11576" )
@RunWith( BytecodeEnhancerRunner.class )
public class LazyCollectionDeletedTest extends BaseCoreFunctionalTestCase {
private Long postId;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Post.class, Tag.class, AdditionalDetails.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
} );
doInHibernate( this::sessionFactory, s -> {
Post post = new Post();
Tag tag1 = new Tag( "tag1" );
Tag tag2 = new Tag( "tag2" );
Set<Tag> tagSet = new HashSet<>();
tagSet.add( tag1 );
tagSet.add( tag2 );
post.tags = tagSet;
AdditionalDetails details = new AdditionalDetails();
details.post = post;
details.details = "Some data";
post.additionalDetails = details;
postId = (Long) s.save( post );
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
Query query = s.createQuery( "from AdditionalDetails where id=" + postId );
AdditionalDetails additionalDetails = (AdditionalDetails) query.getSingleResult();
additionalDetails.details = "New data";
s.persist( additionalDetails );
// additionalDetais.post.tags get deleted on commit
} );
doInHibernate( this::sessionFactory, s -> {
Query query = s.createQuery( "from Post where id=" + postId );
Post retrievedPost = (Post) query.getSingleResult();
assertFalse( "No tags found", retrievedPost.tags.isEmpty() );
retrievedPost.tags.forEach( tag -> System.out.println( "Found tag: " + tag ) );
} );
}
// --- //
@Entity( name = "Tag" )
@Table( name = "TAG" )
private static class Tag {
@Id
@GeneratedValue
Long id;
String name;
Tag() {
}
Tag(String name) {
this.name = name;
}
}
@Entity( name = "Post" )
@Table( name = "POST" )
private static class Post {
@Id
@GeneratedValue
Long id;
@ManyToMany( cascade = CascadeType.ALL )
Set<Tag> tags;
@OneToOne( fetch = FetchType.LAZY, mappedBy = "post", cascade = CascadeType.ALL )
AdditionalDetails additionalDetails;
}
@Entity( name = "AdditionalDetails" )
@Table( name = "ADDITIONAL_DETAILS" )
private static class AdditionalDetails {
@Id
Long id;
String details;
@OneToOne( optional = false )
@MapsId
Post post;
}
}

View File

@ -0,0 +1,165 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.Hibernate.isPropertyInitialized;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Simple test for lazy collection handling in the new bytecode support.
* Prior to HHH-10055 lazy collections were simply not handled. The tests
* initially added for HHH-10055 cover the more complicated case of handling
* lazy collection initialization outside of a transaction; that is a bigger
* fix, and I first want to get collection handling to work here in general.
*
* @author Steve Ebersole
*/
@TestForIssue( jiraKey = "HHH-10055" )
@RunWith( BytecodeEnhancerRunner.class )
public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase {
private static final int CHILDREN_SIZE = 10;
private Long parentID;
private Parent parent;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class, Child.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
} );
doInHibernate( this::sessionFactory, s -> {
Parent parent = new Parent();
parent.setChildren( new ArrayList<>() );
for ( int i = 0; i < CHILDREN_SIZE; i++ ) {
Child child = new Child();
child.parent = parent;
s.persist( child );
}
s.persist( parent );
parentID = parent.id;
} );
}
@Test
public void testTransaction() {
doInHibernate( this::sessionFactory, s -> {
Parent parent = s.load( Parent.class, parentID );
assertThat( parent, notNullValue() );
assertThat( parent, not( instanceOf( HibernateProxy.class ) ) );
assertThat( parent, not( instanceOf( HibernateProxy.class ) ) );
assertFalse( isPropertyInitialized( parent, "children" ) );
checkDirtyTracking( parent );
List children1 = parent.children;
List children2 = parent.children;
assertTrue( isPropertyInitialized( parent, "children" ) );
checkDirtyTracking( parent );
assertThat( children1, sameInstance( children2 ) );
assertThat( children1.size(), equalTo( CHILDREN_SIZE ) );
} );
}
@Test
public void testNoTransaction() {
doInHibernate( this::sessionFactory, s -> {
parent = s.load( Parent.class, parentID );
assertThat( parent, notNullValue() );
assertThat( parent, not( instanceOf( HibernateProxy.class ) ) );
assertThat( parent, not( instanceOf( HibernateProxy.class ) ) );
assertFalse( isPropertyInitialized( parent, "children" ) );
} );
List children1 = parent.children;
List children2 = parent.children;
assertTrue( isPropertyInitialized( parent, "children" ) );
checkDirtyTracking( parent );
assertThat( children1, sameInstance( children2 ) );
assertThat( children1.size(), equalTo( CHILDREN_SIZE ) );
}
// --- //
@Entity
@Table( name = "PARENT" )
private static class Parent {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@OneToMany( mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
List<Child> children;
void setChildren(List<Child> children) {
this.children = children;
}
}
@Entity
@Table( name = "CHILD" )
private static class Child {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@ManyToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
@LazyToOne( LazyToOneOption.NO_PROXY )
Parent parent;
String name;
Child() {
}
Child(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,130 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class LazyLoadingIntegrationTest extends BaseCoreFunctionalTestCase {
private static final int CHILDREN_SIZE = 10;
private Long lastChildID;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class, Child.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
} );
doInHibernate( this::sessionFactory, s -> {
Parent parent = new Parent();
for ( int i = 0; i < CHILDREN_SIZE; i++ ) {
Child child = new Child();
// Association management should kick in here
child.parent = parent;
s.persist( child );
lastChildID = child.id;
}
s.persist( parent );
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
Child loadedChild = s.load( Child.class, lastChildID );
checkDirtyTracking( loadedChild );
loadedChild.name = "Barrabas";
checkDirtyTracking( loadedChild, "name" );
Parent loadedParent = loadedChild.parent;
checkDirtyTracking( loadedChild, "name" );
checkDirtyTracking( loadedParent );
List<Child> loadedChildren = new ArrayList<>( loadedParent.children );
loadedChildren.remove( 0 );
loadedChildren.remove( loadedChild );
loadedParent.setChildren( loadedChildren );
Assert.assertNull( loadedChild.parent );
} );
}
// --- //
@Entity
@Table( name = "PARENT" )
private static class Parent {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@OneToMany( mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
List<Child> children;
void setChildren(List<Child> children) {
this.children = children;
}
}
@Entity
@Table( name = "CHILD" )
private static class Child {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@ManyToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
@LazyToOne( LazyToOneOption.NO_PROXY )
Parent parent;
String name;
Child() {
}
Child(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,160 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.getFieldByReflection;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class LazyLoadingTest extends BaseCoreFunctionalTestCase {
private static final int CHILDREN_SIZE = 10;
private Long parentID;
private Long lastChildID;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class, Child.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
} );
doInHibernate( this::sessionFactory, s -> {
Parent parent = new Parent();
for ( int i = 0; i < CHILDREN_SIZE; i++ ) {
Child child = new Child( "Child #" + i );
child.parent = parent;
parent.addChild( child );
s.persist( child );
lastChildID = child.id;
}
s.persist( parent );
parentID = parent.id;
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
Child loadedChild = s.load( Child.class, lastChildID );
Object nameByReflection = getFieldByReflection( loadedChild, "name" );
assertNotNull( "Non-lazy field 'name' was not loaded", nameByReflection );
Object parentByReflection = getFieldByReflection( loadedChild, "parent" );
assertNull( "Lazy field 'parent' is initialized", parentByReflection );
assertFalse( loadedChild instanceof HibernateProxy );
Parent loadedParent = loadedChild.parent;
assertThat( loadedChild.name, notNullValue() );
assertThat( loadedParent, notNullValue() );
assertThat( loadedChild.parent, notNullValue() );
checkDirtyTracking( loadedChild );
parentByReflection = getFieldByReflection( loadedChild, "parent" );
Object childrenByReflection = getFieldByReflection( loadedParent, "children" );
assertNotNull( "Lazy field 'parent' is not loaded", parentByReflection );
assertNull( "Lazy field 'children' is initialized", childrenByReflection );
assertFalse( loadedParent instanceof HibernateProxy );
assertEquals( parentID, loadedParent.id );
Collection<Child> loadedChildren = loadedParent.children;
checkDirtyTracking( loadedChild );
checkDirtyTracking( loadedParent );
childrenByReflection = getFieldByReflection( loadedParent, "children" );
assertNotNull( "Lazy field 'children' is not loaded", childrenByReflection );
assertFalse( loadedChildren instanceof HibernateProxy );
assertEquals( CHILDREN_SIZE, loadedChildren.size() );
assertTrue( loadedChildren.contains( loadedChild ) );
} );
}
// --- //
@Entity
@Table( name = "PARENT" )
private static class Parent {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@OneToMany( mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
List<Child> children;
void addChild(Child child) {
if ( children == null ) {
children = new ArrayList<>();
}
children.add( child );
}
}
@Entity
@Table( name = "CHILD" )
private static class Child {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@ManyToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
@LazyToOne( LazyToOneOption.NO_PROXY )
Parent parent;
String name;
Child() {
}
Child(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,139 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.LoadEvent;
import org.hibernate.event.spi.LoadEventListener;
import org.hibernate.jpa.event.internal.core.JpaFlushEventListener;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-10922" )
@RunWith( BytecodeEnhancerRunner.class )
@CustomEnhancementContext( {EnhancerTestContext.class, LazyProxyOnEnhancedEntityTest.NoLazyLoadingContext.class} )
public class LazyProxyOnEnhancedEntityTest extends BaseCoreFunctionalTestCase {
private Long parentID;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class, Child.class};
}
@Before
public void prepare() {
buildSessionFactory();
doInJPA( this::sessionFactory, em -> {
Child c = new Child();
em.persist( c );
Parent parent = new Parent();
parent.setChild( c );
em.persist( parent );
parentID = parent.getId();
} );
}
@Test
public void test() {
EventListenerRegistry registry = sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
registry.prependListeners( EventType.FLUSH, new JpaFlushEventListener() );
registry.prependListeners( EventType.LOAD, new ImmediateLoadTrap() );
doInJPA( this::sessionFactory, em -> {
em.find( Parent.class, parentID );
// unwanted lazy load occurs on flush
} );
}
private static class ImmediateLoadTrap implements LoadEventListener {
@Override
public void onLoad(LoadEvent event, LoadType loadType) throws HibernateException {
if ( IMMEDIATE_LOAD == loadType ) {
String msg = loadType + ":" + event.getEntityClassName() + "#" + event.getEntityId();
throw new RuntimeException( msg );
}
}
}
// --- //
@Entity
@Table( name = "PARENT" )
private static class Parent {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
@OneToOne( fetch = FetchType.LAZY
)
Child child;
public Long getId() {
return id;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
@Entity
@Table( name = "CHILD" )
private static class Child {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
String name;
Child() {
// No-arg constructor necessary for proxy factory
}
}
// --- //
public static class NoLazyLoadingContext extends EnhancerTestContext {
@Override
public boolean hasLazyLoadableAttributes(UnloadedClass classDescriptor) {
return false;
}
}
}

View File

@ -0,0 +1,131 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy.basic;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import static org.hibernate.Hibernate.isPropertyInitialized;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
@RunWith( BytecodeEnhancerRunner.class )
public class LazyBasicFieldAccessTest extends BaseCoreFunctionalTestCase {
private LazyEntity entity;
private Long entityId;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{LazyEntity.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
} );
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = new LazyEntity();
entity.setDescription( "desc" );
s.persist( entity );
entityId = entity.id;
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
entity = s.get( LazyEntity.class, entityId );
Assert.assertFalse( isPropertyInitialized( entity, "description" ) );
checkDirtyTracking( entity );
assertEquals( "desc", entity.getDescription() );
assertTrue( isPropertyInitialized( entity, "description" ) );
} );
doInHibernate( this::sessionFactory, s -> {
entity.setDescription( "desc1" );
s.update( entity );
//Assert.assertFalse( Hibernate.isPropertyInitialized( entity, "description" ) );
checkDirtyTracking( entity, "description" );
assertEquals( "desc1", entity.getDescription() );
assertTrue( isPropertyInitialized( entity, "description" ) );
} );
doInHibernate( this::sessionFactory, s -> {
entity = s.get( LazyEntity.class, entityId );
assertEquals( "desc1", entity.getDescription() );
} );
doInHibernate( this::sessionFactory, s -> {
entity.setDescription( "desc2" );
LazyEntity mergedEntity = (LazyEntity) s.merge( entity );
// Assert.assertFalse( isPropertyInitialized( entity, "description" ) );
checkDirtyTracking( mergedEntity, "description" );
assertEquals( "desc2", mergedEntity.getDescription() );
assertTrue( isPropertyInitialized( mergedEntity, "description" ) );
} );
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = s.get( LazyEntity.class, entityId );
assertEquals( "desc2", entity.getDescription() );
} );
}
// --- //
@Entity
@Table( name = "LAZY_FIELD_ENTITY" )
private static class LazyEntity {
Long id;
String description;
@Id
@GeneratedValue
Long getId() {
return id;
}
void setId(Long id) {
this.id = id;
}
@Basic( fetch = FetchType.LAZY )
String getDescription() {
return description;
}
void setDescription(String description) {
this.description = description;
}
}
}

View File

@ -0,0 +1,121 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy.basic;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import static org.hibernate.Hibernate.isPropertyInitialized;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
@RunWith( BytecodeEnhancerRunner.class )
public class LazyBasicPropertyAccessTest extends BaseCoreFunctionalTestCase {
private LazyEntity entity;
private Long entityId;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{LazyEntity.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
} );
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = new LazyEntity();
entity.description = "desc";
s.persist( entity );
entityId = entity.id;
} );
}
@Test
public void execute() {
doInHibernate( this::sessionFactory, s -> {
entity = s.get( LazyEntity.class, entityId );
Assert.assertFalse( isPropertyInitialized( entity, "description" ) );
checkDirtyTracking( entity );
assertEquals( "desc", entity.description );
assertTrue( isPropertyInitialized( entity, "description" ) );
} );
doInHibernate( this::sessionFactory, s -> {
entity.description = "desc1";
s.update( entity );
// Assert.assertFalse( Hibernate.isPropertyInitialized( entity, "description" ) );
checkDirtyTracking( entity, "description" );
assertEquals( "desc1", entity.description );
assertTrue( isPropertyInitialized( entity, "description" ) );
} );
doInHibernate( this::sessionFactory, s -> {
entity = s.get( LazyEntity.class, entityId );
assertEquals( "desc1", entity.description );
} );
doInHibernate( this::sessionFactory, s -> {
entity.description = "desc2";
LazyEntity mergedEntity = (LazyEntity) s.merge( entity );
//Assert.assertFalse( Hibernate.isPropertyInitialized( entity, "description" ) );
checkDirtyTracking( mergedEntity, "description" );
assertEquals( "desc2", mergedEntity.description );
assertTrue( isPropertyInitialized( mergedEntity, "description" ) );
} );
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = s.get( LazyEntity.class, entityId );
assertEquals( "desc2", entity.description );
} );
}
// --- //
@Entity
@Access( AccessType.FIELD )
@Table( name = "LAZY_PROPERTY_ENTITY" )
private static class LazyEntity {
@Id
@GeneratedValue
Long id;
@Basic( fetch = FetchType.LAZY )
String description;
}
}

View File

@ -0,0 +1,118 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy.cache;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Type;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class LazyInCacheTest extends BaseCoreFunctionalTestCase {
private Long orderId;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Order.class, Product.class, Tag.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
} );
Order order = new Order();
Product product = new Product();
order.products.add( product );
order.data = "some data".getBytes( Charset.defaultCharset() );
doInJPA( this::sessionFactory, em -> {
em.persist( product );
em.persist( order );
} );
orderId = order.id;
}
@Test
public void test() {
doInJPA( this::sessionFactory, em -> {
Order order = em.find( Order.class, orderId );
Assert.assertEquals( 1, order.products.size() );
} );
}
// --- //
@Entity
@Table( name = "ORDER_TABLE" )
@Cache( usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE )
private static class Order {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
Long id;
@OneToMany
List<Product> products = new ArrayList<>();
@OneToMany
List<Tag> tags = new ArrayList<>();
@Basic( fetch = FetchType.LAZY )
@Type( type = "org.hibernate.type.BinaryType" )
byte[] data;
}
@Entity
@Table( name = "PRODUCT" )
private static class Product {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
Long id;
String name;
}
@Entity
@Table( name = "TAG" )
private static class Tag {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
Long id;
String name;
}
}

View File

@ -0,0 +1,274 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy.group;
import org.hibernate.annotations.LazyGroup;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.List;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.getFieldByReflection;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* @author Steve Ebersole
*/
@TestForIssue( jiraKey = "HHH-11155" )
@RunWith( BytecodeEnhancerRunner.class )
public class LazyGroupTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[]{Child.class, Parent.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
} );
doInHibernate( this::sessionFactory, s -> {
Child c1 = new Child( "steve", "Hibernater" );
Child c2 = new Child( "sally", "Joe Mama" );
Parent p1 = new Parent( "Hibernate" );
Parent p2 = new Parent( "Swimming" );
c1.parent = p1;
p1.children.add( c1 );
c1.alternateParent = p2;
p2.alternateChildren.add( c1 );
c2.parent = p2;
p2.children.add( c2 );
c2.alternateParent = p1;
p1.alternateChildren.add( c2 );
s.save( p1 );
s.save( p2 );
} );
}
@Test
@TestForIssue( jiraKey = "HHH-10267" )
public void testAccess() {
doInHibernate( this::sessionFactory, s -> {
Child c1 = (Child) s.createQuery( "from Child c where c.name = :name" ).setParameter( "name", "steve" ).uniqueResult();
// verify the expected initial loaded state
assertLoaded( c1, "name" );
assertNotLoaded( c1, "nickName" );
assertNotLoaded( c1, "parent" );
assertNotLoaded( c1, "alternateParent" );
// Now lets access nickName which ought to initialize nickName and parent, but not alternateParent
c1.getNickName();
assertLoaded( c1, "nickName" );
assertLoaded( c1, "parent" );
assertNotLoaded( c1, "alternateParent" );
assertEquals( "Hibernate", c1.parent.nombre );
assertFalse( c1.parent instanceof HibernateProxy );
Child c2 = (Child) s.createQuery( "from Child c where c.name = :name" ).setParameter( "name", "sally" ).uniqueResult();
// verify the expected initial loaded state
assertLoaded( c2, "name" );
assertNotLoaded( c2, "nickName" );
assertNotLoaded( c2, "parent" );
assertNotLoaded( c2, "alternateParent" );
// Now lets access alternateParent which ought to initialize alternateParent and nothing else
c2.getAlternateParent();
assertNotLoaded( c2, "nickName" );
assertNotLoaded( c2, "parent" );
assertLoaded( c2, "alternateParent" );
assertEquals( "Hibernate", c2.alternateParent.nombre );
assertFalse( c2.alternateParent instanceof HibernateProxy );
} );
}
@Test
@TestForIssue( jiraKey = "HHH-11155" )
public void testUpdate() {
Parent p1New = new Parent();
p1New.nombre = "p1New";
doInHibernate( this::sessionFactory, s -> {
Child c1 = (Child) s.createQuery( "from Child c where c.name = :name" ).setParameter( "name", "steve" ).uniqueResult();
// verify the expected initial loaded state
assertLoaded( c1, "name" );
assertNotLoaded( c1, "nickName" );
assertNotLoaded( c1, "parent" );
assertNotLoaded( c1, "alternateParent" );
// Now lets update nickName which ought to initialize nickName and parent, but not alternateParent
c1.nickName = "new nickName";
assertLoaded( c1, "nickName" );
assertNotLoaded( c1, "parent" );
assertNotLoaded( c1, "alternateParent" );
assertEquals( "Hibernate", c1.parent.nombre );
assertFalse( c1.parent instanceof HibernateProxy );
// Now update c1.parent
c1.parent.children.remove( c1 );
c1.parent = p1New;
p1New.children.add( c1 );
} );
// verify updates
doInHibernate( this::sessionFactory, s -> {
Child c1 = (Child) s.createQuery( "from Child c where c.name = :name" ).setParameter( "name", "steve" ).uniqueResult();
assertEquals( "new nickName", c1.getNickName() );
assertEquals( "p1New", c1.parent.nombre );
assertFalse( c1.parent instanceof HibernateProxy );
} );
doInHibernate( this::sessionFactory, s -> {
Child c2 = (Child) s.createQuery( "from Child c where c.name = :name" ).setParameter( "name", "sally" ).uniqueResult();
// verify the expected initial loaded state
assertLoaded( c2, "name" );
assertNotLoaded( c2, "nickName" );
assertNotLoaded( c2, "parent" );
assertNotLoaded( c2, "alternateParent" );
// Now lets access and update alternateParent which ought to initialize alternateParent and nothing else
Parent p1 = c2.getAlternateParent();
c2.alternateParent = p1New;
assertNotLoaded( c2, "nickName" );
assertNotLoaded( c2, "parent" );
assertLoaded( c2, "alternateParent" );
assertEquals( "p1New", c2.getAlternateParent().nombre );
assertFalse( c2.getAlternateParent() instanceof HibernateProxy );
p1.alternateChildren.remove( c2 );
p1New.alternateChildren.add( c2 );
} );
// verify update
doInHibernate( this::sessionFactory, s -> {
Child c2 = (Child) s.createQuery( "from Child c where c.name = :name" ).setParameter( "name", "sally" ).uniqueResult();
assertEquals( "p1New", c2.getAlternateParent().nombre );
} );
}
@After
public void cleanup() {
doInHibernate( this::sessionFactory, s -> {
s.createQuery( "delete Child" ).executeUpdate();
s.createQuery( "delete Parent" ).executeUpdate();
} );
}
// --- //
private void assertLoaded(Object owner, String name) {
// NOTE we assume null == not-loaded
Object fieldByReflection = getFieldByReflection( owner, name );
assertNotNull( "Expecting field '" + name + "' to be loaded, but it was not", fieldByReflection );
}
private void assertNotLoaded(Object owner, String name) {
// NOTE we assume null == not-loaded
Object fieldByReflection = getFieldByReflection( owner, name );
assertNull( "Expecting field '" + name + "' to be not loaded, but it was", fieldByReflection );
}
// --- //
@Entity( name = "Parent" )
@Table( name = "PARENT" )
private static class Parent {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
String nombre;
@OneToMany( mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
List<Child> children = new ArrayList<>();
@OneToMany( mappedBy = "alternateParent", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
List<Child> alternateChildren = new ArrayList<>();
Parent() {
}
Parent(String nombre) {
this.nombre = nombre;
}
}
@Entity( name = "Child" )
@Table( name = "CHILD" )
private static class Child {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
Long id;
String name;
@Basic( fetch = FetchType.LAZY )
String nickName;
@ManyToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
@LazyToOne( LazyToOneOption.NO_PROXY )
Parent parent;
@ManyToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
@LazyToOne( LazyToOneOption.NO_PROXY )
@LazyGroup( "SECONDARY" )
Parent alternateParent;
Child() {
}
Child(String name, String nickName) {
this.name = name;
this.nickName = nickName;
}
Parent getAlternateParent() {
return alternateParent;
}
String getNickName() {
return nickName;
}
}
}

View File

@ -0,0 +1,143 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.bytecode.enhancement.lazy.group;
import org.hibernate.annotations.LazyGroup;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Table;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.getFieldByReflection;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* @author Steve Ebersole
*/
@TestForIssue( jiraKey = "HHH-11155, HHH-11506" )
@RunWith( BytecodeEnhancerRunner.class )
@CustomEnhancementContext( {EnhancerTestContext.class, SimpleLazyGroupUpdateTest.NoDirtyCheckingContext.class} )
public class SimpleLazyGroupUpdateTest extends BaseCoreFunctionalTestCase {
public static final String REALLY_BIG_STRING = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[]{TestEntity.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
} );
doInHibernate( this::sessionFactory, s -> {
s.save( new TestEntity( 1L, "entity 1", "blah", REALLY_BIG_STRING ) );
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
TestEntity entity = s.load( TestEntity.class, 1L );
assertLoaded( entity, "name" );
assertNotLoaded( entity, "lifeStory" );
assertNotLoaded( entity, "reallyBigString" );
entity.lifeStory = "blah blah blah";
assertLoaded( entity, "name" );
assertLoaded( entity, "lifeStory" );
assertNotLoaded( entity, "reallyBigString" );
} );
doInHibernate( this::sessionFactory, s -> {
TestEntity entity = s.load( TestEntity.class, 1L );
assertLoaded( entity, "name" );
assertNotLoaded( entity, "lifeStory" );
assertNotLoaded( entity, "reallyBigString" );
assertEquals( "blah blah blah", entity.lifeStory );
assertEquals( REALLY_BIG_STRING, entity.reallyBigString );
} );
}
private void assertLoaded(Object owner, String name) {
// NOTE we assume null == not-loaded
Object fieldByReflection = getFieldByReflection( owner, name );
assertNotNull( "Expecting field '" + name + "' to be loaded, but it was not", fieldByReflection );
}
private void assertNotLoaded(Object owner, String name) {
// NOTE we assume null == not-loaded
Object fieldByReflection = getFieldByReflection( owner, name );
assertNull( "Expecting field '" + name + "' to be not loaded, but it was", fieldByReflection );
}
@After
public void cleanup() {
doInHibernate( this::sessionFactory, s -> {
s.createQuery( "delete TestEntity" ).executeUpdate();
} );
}
// --- //
@Entity( name = "TestEntity" )
@Table( name = "TEST_ENTITY" )
private static class TestEntity {
@Id
Long id;
String name;
@Basic( fetch = FetchType.LAZY )
@LazyGroup( "grp1" )
String lifeStory;
@Basic( fetch = FetchType.LAZY )
@LazyGroup( "grp2" )
String reallyBigString;
TestEntity() {
}
TestEntity(Long id, String name, String lifeStory, String reallyBigString) {
this.id = id;
this.name = name;
this.lifeStory = lifeStory;
this.reallyBigString = reallyBigString;
}
}
// --- //
public static class NoDirtyCheckingContext extends EnhancerTestContext {
@Override
public boolean doDirtyCheckingInline(UnloadedClass classDescriptor) {
return false;
}
}
}

View File

@ -0,0 +1,143 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazyCache;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Formula;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.cache.BaseRegion;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
import java.util.Locale;
import static org.hibernate.Hibernate.isPropertyInitialized;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Steve Ebersole
*/
@RunWith( BytecodeEnhancerRunner.class )
public class InitFromCacheTest extends BaseCoreFunctionalTestCase {
private EntityPersister persister;
private Long documentID;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[]{Document.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
configuration.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" );
} );
persister = sessionFactory().getMetamodel().entityPersister( Document.class );
assertTrue( persister.hasCache() );
doInHibernate( this::sessionFactory, s -> {
Document document = new Document( "HiA", "Hibernate book", "Hibernate is...." );
s.persist( document );
documentID = document.id;
} );
}
@Test
public void execute() {
doInHibernate( this::sessionFactory, s -> {
Document d = (Document) s.createQuery( "from Document fetch all properties" ).uniqueResult();
assertTrue( isPropertyInitialized( d, "text" ) );
assertTrue( isPropertyInitialized( d, "summary" ) );
BaseRegion region = (BaseRegion) persister.getCacheAccessStrategy().getRegion();
Object cacheKey = persister.getCacheAccessStrategy().generateCacheKey( d.id, persister, sessionFactory(), null );
StandardCacheEntryImpl cacheEntry = (StandardCacheEntryImpl) region.getDataMap().get( cacheKey );
assertNotNull( cacheEntry );
} );
sessionFactory().getStatistics().clear();
doInHibernate( this::sessionFactory, s -> {
Document d = (Document) s.createCriteria( Document.class ).uniqueResult();
assertFalse( isPropertyInitialized( d, "text" ) );
assertFalse( isPropertyInitialized( d, "summary" ) );
assertEquals( "Hibernate is....", d.text );
assertTrue( isPropertyInitialized( d, "text" ) );
assertTrue( isPropertyInitialized( d, "summary" ) );
} );
assertEquals( 2, sessionFactory().getStatistics().getPrepareStatementCount() );
doInHibernate( this::sessionFactory, s -> {
Document d = s.get( Document.class, documentID );
assertFalse( isPropertyInitialized( d, "text" ) );
assertFalse( isPropertyInitialized( d, "summary" ) );
} );
}
// --- //
@Entity( name = "Document" )
@Table( name = "DOCUMENT" )
@Cacheable
@Cache( usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy", region = "foo" )
private static class Document {
@Id
@GeneratedValue
Long id;
String name;
@Basic( fetch = FetchType.LAZY )
@Formula( "upper(name)" )
String upperCaseName;
@Basic( fetch = FetchType.LAZY )
String summary;
@Basic( fetch = FetchType.LAZY )
String text;
@Basic( fetch = FetchType.LAZY )
Date lastTextModification;
Document() {
}
Document(String name, String summary, String text) {
this.lastTextModification = new Date();
this.name = name;
this.upperCaseName = name.toUpperCase( Locale.ROOT );
this.summary = summary;
this.text = text;
}
}
}

View File

@ -0,0 +1,145 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.merge;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Basic;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import java.util.Arrays;
import java.util.List;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
/**
* @author Luis Barreiro
*/
@RunWith( BytecodeEnhancerRunner.class )
public class CompositeMergeTest extends BaseCoreFunctionalTestCase {
private long entityId;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{ParentEntity.class, Address.class, Country.class};
}
@Before
public void prepare() {
buildSessionFactory();
ParentEntity parent = new ParentEntity();
parent.description = "desc";
parent.address = new Address();
parent.address.street = "Sesame street";
parent.address.country = new Country();
parent.address.country.name = "Suriname";
parent.address.country.languages = Arrays.asList( "english", "spanish" );
parent.lazyField = new byte[100];
doInHibernate( this::sessionFactory, s -> {
s.persist( parent );
} );
checkDirtyTracking( parent );
entityId = parent.id;
}
@Test
public void test() {
ParentEntity[] parent = new ParentEntity[3];
doInHibernate( this::sessionFactory, s -> {
parent[0] = s.get( ParentEntity.class, entityId );
} );
checkDirtyTracking( parent[0] );
parent[0].address.country.name = "Paraguai";
checkDirtyTracking( parent[0], "address.country" );
doInHibernate( this::sessionFactory, s -> {
parent[1] = (ParentEntity) s.merge( parent[0] );
checkDirtyTracking( parent[0], "address.country" );
checkDirtyTracking( parent[1], "address.country" );
} );
checkDirtyTracking( parent[0], "address.country" );
checkDirtyTracking( parent[1] );
parent[1].address.country.name = "Honduras";
checkDirtyTracking( parent[1], "address.country" );
doInHibernate( this::sessionFactory, s -> {
s.saveOrUpdate( parent[1] );
checkDirtyTracking( parent[1], "address.country" );
} );
doInHibernate( this::sessionFactory, s -> {
parent[2] = s.get( ParentEntity.class, entityId );
Assert.assertEquals( "Honduras", parent[2].address.country.name );
} );
}
// --- //
@Entity
@Table( name = "PARENT_ENTITY" )
private static class ParentEntity {
@Id
@GeneratedValue
Long id;
String description;
@Embedded
Address address;
@Basic( fetch = FetchType.LAZY )
byte[] lazyField;
}
@Embeddable
@Table( name = "ADDRESS" )
private static class Address {
String street;
@Embedded
Country country;
}
@Embeddable
@Table( name = "COUNTRY" )
private static class Country {
String name;
@ElementCollection
@CollectionTable( name = "languages", joinColumns = @JoinColumn( name = "id", referencedColumnName = "id" ) )
List<String> languages;
}
}

View File

@ -0,0 +1,111 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.merge;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.List;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.fail;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-11459" )
@RunWith( BytecodeEnhancerRunner.class )
public class MergeEnhancedEntityTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Person.class, PersonAddress.class};
}
@Before
public void prepare() {
buildSessionFactory();
doInHibernate( this::sessionFactory, s -> {
s.persist( new Person( 1L, "Sam" ) );
} );
}
@Test
public void testMerge() {
doInHibernate( this::sessionFactory, s -> {
Person entity = s.find( Person.class, 1L );
entity.name = "John";
try {
s.merge( entity );
} catch ( RuntimeException e ) {
fail( "Enhanced entity can't be merged: " + e.getMessage() );
}
} );
}
@Test
public void testRefresh() {
doInHibernate( this::sessionFactory, s -> {
Person entity = s.find( Person.class, 1L );
entity.name = "John";
try {
s.refresh( entity );
} catch ( RuntimeException e ) {
fail( "Enhanced entity can't be refreshed: " + e.getMessage() );
}
} );
}
// --- //
@Entity
@Table( name = "PERSON" )
private static class Person {
@Id
Long id;
@Column( name = "name", length = 10, nullable = false )
String name;
@OneToMany( fetch = FetchType.LAZY, mappedBy = "parent", orphanRemoval = true, cascade = CascadeType.ALL )
List<PersonAddress> details = new ArrayList<>();
Person() {
}
Person(Long id, String name) {
this.id = id;
this.name = name;
}
}
@Entity
@Table( name = "PERSON_ADDRESS" )
private static class PersonAddress {
@Id
Long id;
@ManyToOne( optional = false, fetch = FetchType.LAZY )
Person parent;
}
}

View File

@ -0,0 +1,279 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.ondemandload;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hibernate.Hibernate.isPropertyInitialized;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Luis Barreiro
*/
@TestForIssue( jiraKey = "HHH-10055" )
@RunWith( BytecodeEnhancerRunner.class )
public class OnDemandLoadTest extends BaseCoreFunctionalTestCase {
@Override
public Class[] getAnnotatedClasses() {
return new Class[]{Store.class, Inventory.class, Product.class};
}
@Before
public void prepare() {
buildSessionFactory( configuration -> {
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
configuration.setProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
configuration.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" );
} );
doInHibernate( this::sessionFactory, s -> {
Store store = new Store( 1L ).setName( "Acme Super Outlet" );
s.persist( store );
Product product = new Product( "007" ).setName( "widget" ).setDescription( "FooBar" );
s.persist( product );
store.addInventoryProduct( product ).setQuantity( 10L ).setStorePrice( new BigDecimal( 500 ) );
} );
}
@Test
public void testClosedSession() {
sessionFactory().getStatistics().clear();
Store[] store = new Store[1];
doInHibernate( this::sessionFactory, s -> {
// first load the store, making sure it is not initialized
store[0] = s.load( Store.class, 1L );
assertNotNull( store[0] );
assertFalse( isPropertyInitialized( store[0], "inventories" ) );
assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 0, sessionFactory().getStatistics().getSessionCloseCount() );
} );
assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() );
store[0].getInventories();
assertTrue( isPropertyInitialized( store[0], "inventories" ) );
assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() );
}
@Test
public void testClearedSession() {
sessionFactory().getStatistics().clear();
doInHibernate( this::sessionFactory, s -> {
// first load the store, making sure collection is not initialized
Store store = s.get( Store.class, 1L );
assertNotNull( store );
assertFalse( isPropertyInitialized( store, "inventories" ) );
assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 0, sessionFactory().getStatistics().getSessionCloseCount() );
// then clear session and try to initialize collection
s.clear();
assertNotNull( store );
assertFalse( isPropertyInitialized( store, "inventories" ) );
store.getInventories().size();
assertTrue( isPropertyInitialized( store, "inventories" ) );
// the extra Session is the temp Session needed to perform the init
assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() );
// clear Session again. The collection should still be recognized as initialized from above
s.clear();
assertNotNull( store );
assertTrue( isPropertyInitialized( store, "inventories" ) );
assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() );
// lets clear the Session again and this time reload the Store
s.clear();
store = s.get( Store.class, 1L );
s.clear();
assertNotNull( store );
// collection should be back to uninitialized since we have a new entity instance
assertFalse( isPropertyInitialized( store, "inventories" ) );
assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() );
store.getInventories().size();
assertTrue( isPropertyInitialized( store, "inventories" ) );
// the extra Session is the temp Session needed to perform the init
assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() );
// clear Session again. The collection should still be recognized as initialized from above
s.clear();
assertNotNull( store );
assertTrue( isPropertyInitialized( store, "inventories" ) );
assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() );
assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() );
} );
}
// --- //
@Entity
@Table( name = "STORE" )
private static class Store {
@Id
Long id;
String name;
@OneToMany( mappedBy = "store", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
List<Inventory> inventories = new ArrayList<>();
@Version
Integer version;
Store() {
}
Store(long id) {
this.id = id;
}
Store setName(String name) {
this.name = name;
return this;
}
Inventory addInventoryProduct(Product product) {
Inventory inventory = new Inventory( this, product );
inventories.add( inventory );
return inventory;
}
public List<Inventory> getInventories() {
return Collections.unmodifiableList( inventories );
}
}
@Entity
@Table( name = "INVENTORY" )
private static class Inventory {
@Id
@GeneratedValue
@GenericGenerator( name = "increment", strategy = "increment" )
Long id = -1L;
@ManyToOne
@JoinColumn( name = "STORE_ID" )
Store store;
@ManyToOne
@JoinColumn( name = "PRODUCT_ID" )
Product product;
Long quantity;
BigDecimal storePrice;
public Inventory() {
}
public Inventory(Store store, Product product) {
this.store = store;
this.product = product;
}
Inventory setStore(Store store) {
this.store = store;
return this;
}
Inventory setProduct(Product product) {
this.product = product;
return this;
}
Inventory setQuantity(Long quantity) {
this.quantity = quantity;
return this;
}
Inventory setStorePrice(BigDecimal storePrice) {
this.storePrice = storePrice;
return this;
}
}
@Entity
@Table( name = "PRODUCT" )
private static class Product {
@Id
String id;
String name;
String description;
BigDecimal msrp;
@Version
Long version;
Product() {
}
Product(String id) {
this.id = id;
}
Product setName(String name) {
this.name = name;
return this;
}
Product setDescription(String description) {
this.description = description;
return this;
}
Product setMsrp(BigDecimal msrp) {
this.msrp = msrp;
return this;
}
}
}

View File

@ -0,0 +1,116 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.otherentityentrycontext;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* This task tests ManagedEntity objects that are already associated with a different PersistenceContext.
*
* @author Gail Badner
*/
@RunWith( BytecodeEnhancerRunner.class )
public class OtherEntityEntryContextTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class};
}
@Before
public void prepare() {
buildSessionFactory();
// Create a Parent
doInHibernate( this::sessionFactory, s -> {
s.persist( new Parent( 1L, "first" ) );
} );
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
Parent p = s.get( Parent.class, 1L );
assertTrue( ManagedEntity.class.isInstance( p ) );
p.name = "second";
assertTrue( s.contains( p ) );
// open another session and evict p from the new session
doInHibernate( this::sessionFactory, session2 -> {
// s2 should contains no entities
assertFalse( session2.contains( p ) );
// evict should do nothing, since p is not associated with s2
session2.evict( p );
assertFalse( session2.contains( p ) );
assertNull( ( (SharedSessionContractImplementor) session2 ).getPersistenceContext().getEntry( p ) );
try {
session2.update( p );
fail( "should have failed because p is already associated with a PersistenceContext that is still open." );
} catch ( HibernateException expected ) {
// expected
}
} );
} );
doInHibernate( this::sessionFactory, s -> {
Parent p = s.get( Parent.class, 1L );
p.name = "third";
s.update( p );
assertTrue( s.contains( p ) );
s.evict( p );
assertFalse( s.contains( p ) );
p = s.get( Parent.class, p.id );
assertEquals( "second", p.name );
} );
}
// --- //
@Entity
@Table( name = "PARENT" )
private static class Parent {
@Id
Long id;
String name;
Parent() {
}
Parent(Long id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,224 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.pk;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.transaction.TransactionUtil;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
import java.io.Serializable;
import java.util.Calendar;
/**
* @author Gail Badner
*/
@RunWith( BytecodeEnhancerRunner.class )
public class EmbeddedPKTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{WorkOrder.class, WorkOrderPK.class};
}
@Before
public void prepare() {
buildSessionFactory();
}
@Test
public void test() {
TransactionUtil.doInHibernate( this::sessionFactory, s -> {
s.persist( new WorkOrder() );
} );
}
// --- //
@Entity
@IdClass( WorkOrderPK.class )
@Table( name = "WORK_ORDER" )
private static class WorkOrder {
@Id
long id;
@Id
long location;
int originalQuantity;
int completedQuantity;
@Temporal( TemporalType.TIMESTAMP )
Calendar dueDate;
@Temporal( TemporalType.TIMESTAMP )
Calendar startDate;
String assemblyId;
@Version
long version;
WorkOrder() {
this( "", 1, 0, Calendar.getInstance() );
}
WorkOrder(String assemblyId, int origQty, int location, Calendar dueDate) {
if ( origQty < 1 ) {
throw new IllegalArgumentException( "WorkOrder can not be created with original quantity " + origQty + ". Must be > 0" );
}
if ( dueDate == null ) {
throw new IllegalArgumentException( "WorkOrder can not be created with null due Date" );
}
this.assemblyId = assemblyId;
this.originalQuantity = origQty;
this.dueDate = dueDate;
this.location = location;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
// --- //
String getAssemblyId() {
return assemblyId;
}
void setAssemblyId(String assemblyId) {
this.assemblyId = assemblyId;
}
int getCompletedQuantity() {
return completedQuantity;
}
void setCompletedQuantity(int compQty) {
this.completedQuantity = compQty;
}
Calendar getDueDate() {
return (Calendar) dueDate.clone();
}
void setDueDate(Calendar dueDate) {
this.dueDate = dueDate;
}
int getOriginalQuantity() {
return originalQuantity;
}
void setOriginalQuantity(int originalQuantity) {
this.originalQuantity = originalQuantity;
}
// --- //
long getLocation() {
return location;
}
void setLocation(int location) {
this.location = location;
}
Calendar getStartDate() {
return (Calendar) startDate.clone();
}
void setStartDate(Calendar instance) {
startDate = instance;
}
long getVersion() {
return version;
}
// Processing methods
boolean update() {
return true;
}
boolean setStatusCompleted() {
return true;
}
void advanceStatus() {
}
void setStatusCancelled() {
}
// --- //
@Override
public boolean equals(Object other) {
return this == other || other != null && other instanceof WorkOrder && id == ( (WorkOrder) other ).id;
}
@Override
public int hashCode() {
return (int) ( id ^ id >>> 32 );
}
@Override
public String toString() {
return "WorkOrder:[" + id + "]";
}
}
private static class WorkOrderPK implements Serializable {
long id;
long location;
WorkOrderPK() {
}
public WorkOrderPK(int location, int id) {
this.location = location;
this.id = id;
}
public long getId() {
return id;
}
public long getLocation() {
return location;
}
// --- //
@Override
public boolean equals(Object other) {
return this == other || other != null && other instanceof WorkOrder && id == ( (WorkOrder) other ).id && location == ( (WorkOrder) other ).location;
}
@Override
public int hashCode() {
return (int) ( 31 * ( id ^ id >>> 32 ) + ( location ^ location >>> 32 ) );
}
}
}

View File

@ -8,7 +8,6 @@ package org.hibernate.test.bytecode.enhancement.tracker;
import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker;
import org.hibernate.engine.spi.CompositeOwner;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@ -24,41 +23,46 @@ public class CompositeOwnerTrackerTest {
public void testCompositeOwnerTracker() {
CompositeOwnerTracker tracker = new CompositeOwnerTracker();
tracker.add("foo", new TestCompositeOwner());
tracker.add( "foo", new TestCompositeOwner() );
tracker.callOwner(".street1");
assertEquals(1, counter);
tracker.add("bar", new TestCompositeOwner());
tracker.callOwner(".city");
assertEquals(3, counter);
tracker.callOwner( ".street1" );
assertEquals( 1, counter );
tracker.add( "bar", new TestCompositeOwner() );
tracker.callOwner( ".city" );
assertEquals( 3, counter );
tracker.removeOwner("foo");
tracker.removeOwner( "foo" );
tracker.callOwner(".country");
assertEquals(4, counter);
tracker.removeOwner("bar");
tracker.callOwner( ".country" );
assertEquals( 4, counter );
tracker.removeOwner( "bar" );
tracker.callOwner(".country");
tracker.callOwner( ".country" );
tracker.add("moo", new TestCompositeOwner());
tracker.callOwner(".country");
assertEquals(5, counter);
tracker.add( "moo", new TestCompositeOwner() );
tracker.callOwner( ".country" );
assertEquals( 5, counter );
}
class TestCompositeOwner implements CompositeOwner {
@Override
public void $$_hibernate_trackChange(String attributeName) {
if(counter == 0)
assertEquals("foo.street1", attributeName);
if(counter == 1)
assertEquals("foo.city", attributeName);
if(counter == 2)
assertEquals("bar.city", attributeName);
if(counter == 3)
assertEquals("bar.country", attributeName);
if(counter == 4)
assertEquals("moo.country", attributeName);
if ( counter == 0 ) {
assertEquals( "foo.street1", attributeName );
}
if ( counter == 1 ) {
assertEquals( "foo.city", attributeName );
}
if ( counter == 2 ) {
assertEquals( "bar.city", attributeName );
}
if ( counter == 3 ) {
assertEquals( "bar.country", attributeName );
}
if ( counter == 4 ) {
assertEquals( "moo.country", attributeName );
}
counter++;
}
}

View File

@ -9,10 +9,10 @@ package org.hibernate.test.bytecode.enhancement.tracker;
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
import org.hibernate.bytecode.enhance.internal.tracker.SortedFieldTracker;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@ -24,69 +24,68 @@ public class DirtyTrackerTest {
@Test
public void testSimpleTracker() {
DirtyTracker tracker = new SimpleFieldTracker();
assertTrue(tracker.isEmpty());
assertTrue(tracker.get().length == 0);
assertTrue( tracker.isEmpty() );
assertEquals( 0, tracker.get().length );
tracker.add("foo");
assertFalse(tracker.isEmpty());
assertArrayEquals(tracker.get(), new String[]{"foo"});
tracker.add( "foo" );
assertFalse( tracker.isEmpty() );
assertArrayEquals( tracker.get(), new String[]{"foo"} );
tracker.clear();
assertTrue(tracker.isEmpty());
assertTrue(tracker.get().length == 0);
assertTrue( tracker.isEmpty() );
assertEquals( 0, tracker.get().length );
tracker.add("foo");
tracker.add("bar");
tracker.add("another.bar");
tracker.add("foo");
tracker.add("another.foo");
tracker.add("another.bar");
assertTrue(tracker.get().length == 4);
tracker.add( "foo" );
tracker.add( "bar" );
tracker.add( "another.bar" );
tracker.add( "foo" );
tracker.add( "another.foo" );
tracker.add( "another.bar" );
assertEquals( 4, tracker.get().length );
tracker.suspend(true);
tracker.add("one more");
assertTrue(tracker.get().length == 4);
tracker.suspend( true );
tracker.add( "one more" );
assertEquals( 4, tracker.get().length );
}
@Test
public void testSortedTracker() {
DirtyTracker tracker = new SortedFieldTracker();
assertTrue(tracker.isEmpty());
assertTrue(tracker.get().length == 0);
assertTrue( tracker.isEmpty() );
assertEquals( 0, tracker.get().length );
tracker.add("foo");
assertFalse(tracker.isEmpty());
assertArrayEquals(tracker.get(), new String[]{"foo"});
tracker.add( "foo" );
assertFalse( tracker.isEmpty() );
assertArrayEquals( tracker.get(), new String[]{"foo"} );
tracker.clear();
assertTrue(tracker.isEmpty());
assertTrue(tracker.get().length == 0);
assertTrue( tracker.isEmpty() );
assertEquals( 0, tracker.get().length );
tracker.add("foo");
tracker.add("bar");
tracker.add("another.bar");
tracker.add("foo");
tracker.add("another.foo");
tracker.add("another.bar");
assertTrue(tracker.get().length == 4);
tracker.add( "foo" );
tracker.add( "bar" );
tracker.add( "another.bar" );
tracker.add( "foo" );
tracker.add( "another.foo" );
tracker.add( "another.bar" );
assertEquals( 4, tracker.get().length );
// we the algorithm for this implementation relies on the fact that the array is kept sorted, so let's check it really is
assertTrue(isSorted(tracker.get()));
// the algorithm for this implementation relies on the fact that the array is kept sorted, so let's check it really is
assertTrue( isSorted( tracker.get() ) );
tracker.suspend(true);
tracker.add("one more");
assertTrue(tracker.get().length == 4);
tracker.suspend( true );
tracker.add( "one more" );
assertEquals( 4, tracker.get().length );
}
private boolean isSorted(String[] arr) {
for (int i = 1; i < arr.length; i++) {
if (arr[i - 1].compareTo(arr[i]) > 0) {
for ( int i = 1; i < arr.length; i++ ) {
if ( arr[i - 1].compareTo( arr[i] ) > 0 ) {
return false;
}
}
return true;
}
}