HHH-14424 Add test for issue

This commit is contained in:
Andrea Boriero 2021-01-29 11:42:57 +01:00
parent 2cf9ec856c
commit 26a46b2010
14 changed files with 1532 additions and 0 deletions

View File

@ -0,0 +1,28 @@
/*
* 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.proxy.inlinedirtychecking;
import java.util.Date;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@MappedSuperclass
public class BaseEntity {
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Id
private Long id;
@Temporal(TemporalType.TIMESTAMP)
private Date createdOn;
}

View File

@ -0,0 +1,45 @@
/*
* 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.proxy.inlinedirtychecking;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;
import javax.persistence.Version;
@Entity(name = "Customer")
public class Customer extends BaseEntity {
@Version
@Column(name = "version")
private int version;
@OneToOne(optional = false, fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST,
CascadeType.MERGE,
CascadeType.REMOVE
})
private User user;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

View File

@ -0,0 +1,240 @@
/*
* 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.proxy.inlinedirtychecking;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@RunWith(BytecodeEnhancerRunner.class)
@CustomEnhancementContext({ NoDirtyCheckEnhancementContext.class, DirtyCheckEnhancementContext.class })
public class EntityWithMutableAttributesTest extends BaseNonConfigCoreFunctionalTestCase {
boolean skipTest;
@Override
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
super.configureStandardServiceRegistryBuilder( ssrb );
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
ssrb.applySetting( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, "100" );
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" );
}
@Override
protected void applyMetadataSources(MetadataSources sources) {
String byteCodeProvider = Environment.getProperties().getProperty( AvailableSettings.BYTECODE_PROVIDER );
if ( byteCodeProvider != null && !Environment.BYTECODE_PROVIDER_NAME_BYTEBUDDY.equals( byteCodeProvider ) ) {
// skip the test if the bytecode provider is Javassist
skipTest = true;
}
else {
sources.addAnnotatedClass( User.class );
sources.addAnnotatedClass( Role.class );
}
}
@Before
public void setUp() {
inTransaction(
session -> {
User user = new User();
user.setId( 1 );
user.setDate( new Date() );
user.setEmail( "not null string" );
Role role = new Role();
role.setId( 2 );
role.setDate( new Date() );
role.setName( "manager" );
user.setRole( role );
session.save( role );
session.save( user );
}
);
}
@After
public void tearDown() {
inTransaction(
session -> {
session.createQuery( "delete from User" ).executeUpdate();
session.createQuery( "delete from Role" ).executeUpdate();
}
);
}
@Test
public void testLoad() {
inTransaction(
session -> {
User user = session.load( User.class, 1 );
assertThat(
user, instanceOf( PersistentAttributeInterceptable.class )
);
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) user;
assertThat(
interceptable.$$_hibernate_getInterceptor(),
instanceOf( EnhancementAsProxyLazinessInterceptor.class )
);
}
);
}
@Test
public void testMutableAttributeIsUpdated() {
inTransaction(
session -> {
User user = session.load( User.class, 1 );
user.getDate().setTime( 0 );
}
);
inTransaction(
session -> {
User user = session.getReference( User.class, 1 );
assertThat( user.getDate().getTime(), is( 0L ) );
}
);
}
@Entity(name = "User")
@Table(name = "appuser")
public static class User {
@Id
private Integer id;
@NotNull
private String email;
private String name;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "t_date")
private Date date;
@ManyToOne
private Role role;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
@Entity(name = "Role")
@Table(name = "approle")
public static class Role {
@Id
private Integer id;
@NotNull
private String name;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "t_date")
private Date date;
private String description;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
}

View File

@ -0,0 +1,251 @@
/*
* 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.proxy.inlinedirtychecking;
import java.util.HashSet;
import java.util.List;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@TestForIssue(jiraKey = "HHH14424")
@RunWith(BytecodeEnhancerRunner.class)
@CustomEnhancementContext({ DirtyCheckEnhancementContext.class, NoDirtyCheckEnhancementContext.class })
public class LoadAndUpdateEntitiesWithCollectionsTest extends BaseNonConfigCoreFunctionalTestCase {
boolean skipTest;
@Override
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
super.configureStandardServiceRegistryBuilder( ssrb );
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
ssrb.applySetting( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, "100" );
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" );
}
@Override
protected void applyMetadataSources(MetadataSources sources) {
String byteCodeProvider = Environment.getProperties().getProperty( AvailableSettings.BYTECODE_PROVIDER );
if ( byteCodeProvider != null && !Environment.BYTECODE_PROVIDER_NAME_BYTEBUDDY.equals( byteCodeProvider ) ) {
// skip the test if the bytecode provider is Javassist
skipTest = true;
}
else {
sources.addAnnotatedClass( SamplingOrder.class );
sources.addAnnotatedClass( Customer.class );
sources.addAnnotatedClass( User.class );
sources.addAnnotatedClass( Role.class );
}
}
@Before
public void setUp() {
inTransaction(
session -> {
User user = new User();
user.setEmail( "foo@bar.com" );
Role role = new Role();
role.setName( "admin" );
user.addRole( role );
Customer customer = new Customer();
customer.setUser( user );
SamplingOrder order = new SamplingOrder();
order.setNote( "it is a sample" );
order.setCustomer( customer );
session.save( user );
session.save( role );
session.save( customer );
session.save( order );
}
);
}
@After
public void tearDwon() {
inTransaction(
session -> {
session.createQuery( "delete from SamplingOrder" ).executeUpdate();
session.createQuery( "delete from Customer" ).executeUpdate();
session.createQuery( "delete from User" ).executeUpdate();
session.createQuery( "delete from Role" ).executeUpdate();
}
);
}
@Test
public void testLoad() {
inTransaction(
session -> {
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<SamplingOrder> cq = cb.createQuery( SamplingOrder.class );
Root<SamplingOrder> root = cq.from( SamplingOrder.class );
root.fetch( SamplingOrder_.customer );
TypedQuery<SamplingOrder> query = session.createQuery( cq );
query.getResultList();
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
}
);
}
@Test
public void testAddUserRoles() {
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrder( session );
User user = samplingOrder.getCustomer().getUser();
Role role = new Role();
role.setName( "superuser" );
user.addRole( role );
session.save( role );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
assertThat( user.getRoles().size(), is( 2 ) );
}
);
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrder( session );
User user = samplingOrder.getCustomer().getUser();
Role role = new Role();
role.setName( "user" );
user.getRoles().add( role );
session.save( role );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
assertThat( user.getRoles().size(), is( 3 ) );
}
);
inTransaction(
session -> {
User user = session
.createQuery(
"from User",
User.class
)
.list()
.get( 0 );
Role role = new Role();
user.getRoles().add( role );
session.save( role );
}
);
inTransaction(
session -> {
List<User> users = session
.createQuery(
"from User u",
User.class
)
.list();
User user = users
.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
assertThat( user.getRoles().size(), is( 4 ) );
}
);
}
@Test
public void testDeleteUserRoles() {
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrder( session );
User user = samplingOrder.getCustomer().getUser();
user.setRoles( new HashSet<>() );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
assertThat( user.getRoles().size(), is( 0 ) );
}
);
}
@Test
public void testModifyUserMail() {
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrder( session );
User user = samplingOrder.getCustomer().getUser();
user.setEmail( "bar@foo.com" );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "bar@foo.com" ) );
assertThat( user.getRoles().size(), is( 1 ) );
}
);
}
private SamplingOrder getSamplingOrder(SessionImplementor session) {
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<SamplingOrder> cq = cb.createQuery( SamplingOrder.class );
Root<SamplingOrder> root = cq.from( SamplingOrder.class );
root.fetch( SamplingOrder_.customer );
TypedQuery<SamplingOrder> query = session.createQuery( cq );
List<SamplingOrder> resultList = query.getResultList();
return resultList.get( 0 );
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.proxy.inlinedirtychecking;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity(name = "Role")
@Table(name = "approle")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.proxy.inlinedirtychecking;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Entity(name = "SamplingOrder")
public class SamplingOrder {
@Id
@GeneratedValue
private Long id;
private String note;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customerId")
private Customer customer;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}

View File

@ -0,0 +1,308 @@
/*
* 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.proxy.inlinedirtychecking;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
@RunWith(BytecodeEnhancerRunner.class)
@CustomEnhancementContext({ NoDirtyCheckEnhancementContext.class, DirtyCheckEnhancementContext.class })
public class SimpleDynamicUpdateTest extends BaseNonConfigCoreFunctionalTestCase {
boolean skipTest;
@Override
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
super.configureStandardServiceRegistryBuilder( ssrb );
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
ssrb.applySetting( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, "100" );
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" );
}
@Override
protected void applyMetadataSources(MetadataSources sources) {
String byteCodeProvider = Environment.getProperties().getProperty( AvailableSettings.BYTECODE_PROVIDER );
if ( byteCodeProvider != null && !Environment.BYTECODE_PROVIDER_NAME_BYTEBUDDY.equals( byteCodeProvider ) ) {
// skip the test if the bytecode provider is Javassist
skipTest = true;
}
else {
sources.addAnnotatedClass( User.class );
sources.addAnnotatedClass( Role.class );
}
}
@Before
public void setUp() {
inTransaction(
session -> {
User user = new User();
user.setId( 1 );
user.setEmail( "not null string" );
Address address = new Address();
address.setState( "Texas" );
user.setAddress( address );
Role role = new Role();
role.setId( 2 );
role.setName( "manager" );
user.setRole( role );
session.save( role );
session.save( user );
}
);
}
@Test
public void testIt() {
inTransaction(
session -> {
User user = session.getReference( User.class, 1 );
assertThat(
user, instanceOf( PersistentAttributeInterceptable.class )
);
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) user;
assertThat(
interceptable.$$_hibernate_getInterceptor(),
instanceOf( EnhancementAsProxyLazinessInterceptor.class )
);
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
entity.setName( "abc" );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
assertThat( entity.getName(), is( "abc" ) );
assertThat( entity.getEmail(), is( "not null string" ) );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
entity.setRole( null );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
assertThat( entity.getName(), is( "abc" ) );
assertThat( entity.getEmail(), is( "not null string" ) );
assertThat( entity.getRole(), is( nullValue() ) );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
entity.setName( null );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
assertThat( entity.getName(), is( nullValue() ) );
assertThat( entity.getEmail(), is( "not null string" ) );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
entity.setAddress( null );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
assertThat( entity.getName(), is( nullValue() ) );
assertThat( entity.getEmail(), is( "not null string" ) );
assertThat( entity.getRole(), is( nullValue() ) );
assertThat( entity.getAddress(), is( nullValue() ) );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
Role role = new Role();
role.setId( 3 );
role.setName( "user" );
entity.setRole( role );
session.save( role );
}
);
inTransaction(
session -> {
User entity = session.getReference( User.class, 1 );
assertThat( entity.getName(), is( nullValue() ) );
assertThat( entity.getEmail(), is( "not null string" ) );
assertThat( entity.getRole(), is( notNullValue() ) );
assertThat( entity.getAddress(), is( nullValue() ) );
}
);
}
@Entity(name = "User")
@Table(name = "appuser")
@DynamicUpdate
public static class User {
@Id
private Integer id;
@NotNull
private String email;
private String name;
private Address address;
@ManyToOne
private Role role;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
@Entity(name = "Role")
@Table(name = "approle")
@DynamicUpdate
public static class Role {
@Id
private Integer id;
@NotNull
private String name;
private String description;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
@Embeddable
public static class Address {
private String street;
private String state;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.proxy.inlinedirtychecking;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Entity(name = "User")
@Table(name = "appuser")
public class User extends BaseEntity {
@Column(unique = true, nullable = false)
@NotNull
private String email;
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_in_role", joinColumns = @JoinColumn(name = "userid"), inverseJoinColumns = @JoinColumn(name = "roleid"))
public Set<Role> roles = new HashSet<>();
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public void addRole(Role role) {
this.roles.add( role );
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.proxy.inlinedirtychecking.dynamicupdate;
import java.util.Date;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@MappedSuperclass
public class BaseEntity {
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Id
private Long id;
@Temporal(TemporalType.TIMESTAMP)
private Date createdOn;
}

View File

@ -0,0 +1,48 @@
/*
* 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.proxy.inlinedirtychecking.dynamicupdate;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;
import javax.persistence.Version;
import org.hibernate.annotations.DynamicUpdate;
@Entity(name = "Customer")
@DynamicUpdate
public class Customer extends BaseEntity {
@Version
@Column(name = "version")
private int version;
@OneToOne(optional = false, fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST,
CascadeType.MERGE,
CascadeType.REMOVE
})
private User user;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

View File

@ -0,0 +1,258 @@
/*
* 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.proxy.inlinedirtychecking.dynamicupdate;
import java.util.HashSet;
import java.util.List;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.DirtyCheckEnhancementContext;
import org.hibernate.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.NoDirtyCheckEnhancementContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
@TestForIssue(jiraKey = "HHH14424")
@RunWith(BytecodeEnhancerRunner.class)
@CustomEnhancementContext({ NoDirtyCheckEnhancementContext.class, DirtyCheckEnhancementContext.class })
public class DynamicUpdateAndCollectionsTest extends BaseNonConfigCoreFunctionalTestCase {
boolean skipTest;
@Override
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
super.configureStandardServiceRegistryBuilder( ssrb );
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
ssrb.applySetting( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, "100" );
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" );
}
@Override
protected void applyMetadataSources(MetadataSources sources) {
String byteCodeProvider = Environment.getProperties().getProperty( AvailableSettings.BYTECODE_PROVIDER );
if ( byteCodeProvider != null && !Environment.BYTECODE_PROVIDER_NAME_BYTEBUDDY.equals( byteCodeProvider ) ) {
// skip the test if the bytecode provider is Javassist
skipTest = true;
}
else {
sources.addAnnotatedClass( SamplingOrder.class );
sources.addAnnotatedClass( Customer.class );
sources.addAnnotatedClass( User.class );
sources.addAnnotatedClass( Role.class );
}
}
@Before
public void setUp() {
inTransaction(
session -> {
User user = new User();
user.setEmail( "foo@bar.com" );
Role role = new Role();
role.setName( "admin" );
user.addRole( role );
Customer customer = new Customer();
customer.setUser( user );
SamplingOrder order = new SamplingOrder();
order.setNote( "it is a sample" );
order.setCustomer( customer );
session.save( user );
session.save( role );
session.save( customer );
session.save( order );
}
);
}
@After
public void tearDwon() {
inTransaction(
session -> {
session.createQuery( "delete from SamplingOrder" ).executeUpdate();
session.createQuery( "delete from Customer" ).executeUpdate();
session.createQuery( "delete from User" ).executeUpdate();
session.createQuery( "delete from Role" ).executeUpdate();
}
);
}
@Test
public void testLoad() {
inTransaction(
session -> {
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<SamplingOrder> cq = cb.createQuery( SamplingOrder.class );
Root<SamplingOrder> root = cq.from( SamplingOrder.class );
root.fetch( SamplingOrder_.customer );
TypedQuery<SamplingOrder> query = session.createQuery( cq );
query.getResultList();
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
}
);
}
@Test
public void testRemoveCustomers() {
Long samplingOrderId = fromTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrderFetchCustomer( session );
samplingOrder.setCustomer( null );
return samplingOrder.getId();
}
);
inTransaction(
session -> {
SamplingOrder samplingOrder = session.get( SamplingOrder.class, samplingOrderId );
assertThat( samplingOrder.getCustomer(), is( nullValue() ) );
}
);
}
@Test
public void testAddUserRoles() {
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrderFetchCustomer( session );
User user = samplingOrder.getCustomer().getUser();
Role role = new Role();
role.setName( "superuser" );
user.addRole( role );
session.save( role );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
assertThat( user.getRoles().size(), is( 2 ) );
}
);
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrderFetchCustomer( session );
User user = samplingOrder.getCustomer().getUser();
Role role = new Role();
user.getRoles().add( role );
session.save( role );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
assertThat( user.getRoles().size(), is( 3 ) );
}
);
inTransaction(
session -> {
User user = session.createQuery( "from User", User.class ).list().get( 0 );
Role role = new Role();
user.getRoles().add( role );
session.save( role );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "foo@bar.com" ) );
assertThat( user.getRoles().size(), is( 4 ) );
}
);
}
@Test
public void testDeleteUserRoles() {
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrderFetchCustomer( session );
User user = samplingOrder.getCustomer().getUser();
user.setRoles( new HashSet<>() );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getRoles().size(), is( 0 ) );
}
);
}
@Test
public void testModifyUserMail() {
inTransaction(
session -> {
SamplingOrder samplingOrder = getSamplingOrderFetchCustomer( session );
User user = samplingOrder.getCustomer().getUser();
user.setEmail( "bar@foo.com" );
}
);
inTransaction(
session -> {
List<User> users = session.createQuery( "from User u", User.class ).list();
User user = users.get( 0 );
assertThat( user.getEmail(), is( "bar@foo.com" ) );
assertThat( user.getRoles().size(), is( 1 ) );
}
);
}
private SamplingOrder getSamplingOrderFetchCustomer(SessionImplementor session) {
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<SamplingOrder> cq = cb.createQuery( SamplingOrder.class );
Root<SamplingOrder> root = cq.from( SamplingOrder.class );
root.fetch( SamplingOrder_.customer );
TypedQuery<SamplingOrder> query = session.createQuery( cq );
List<SamplingOrder> resultList = query.getResultList();
return resultList.get( 0 );
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.proxy.inlinedirtychecking.dynamicupdate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicUpdate;
@Entity(name = "Role")
@Table(name = "approle")
@DynamicUpdate
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.proxy.inlinedirtychecking.dynamicupdate;
import java.util.List;
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 org.hibernate.annotations.DynamicUpdate;
@Entity(name = "SamplingOrder")
@DynamicUpdate
public class SamplingOrder {
@Id
@GeneratedValue
private Long id;
private String note;
@OneToMany
private List<Customer> customers;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customerId")
private Customer customer;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.proxy.inlinedirtychecking.dynamicupdate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.annotations.DynamicUpdate;
@Entity(name = "User")
@Table(name = "appuser")
@DynamicUpdate
public class User extends BaseEntity {
@Column( unique = true, nullable = false)
@NotNull
private String email;
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_in_role", joinColumns = @JoinColumn(name = "userid"), inverseJoinColumns = @JoinColumn(name = "roleid"))
public Set<Role> roles = new HashSet<>();
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public void addRole(Role role) {
this.roles.add( role );
}
}