Skip to content

Commit

Permalink
[hibernate#1641] first draft of @struct tests
Browse files Browse the repository at this point in the history
  • Loading branch information
blafond committed Jan 24, 2024
1 parent c45ec94 commit 9cf65f3
Show file tree
Hide file tree
Showing 2 changed files with 309 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.reactive;

import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.List;

import org.hibernate.annotations.Struct;
import org.hibernate.reactive.annotations.EnabledFor;
import org.hibernate.reactive.logging.impl.Log;
import org.hibernate.reactive.logging.impl.LoggerFactory;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.vertx.junit5.Timeout;
import io.vertx.junit5.VertxTestContext;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

import static java.util.concurrent.TimeUnit.MINUTES;
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2;
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.POSTGRESQL;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@Timeout(value = 10, timeUnit = MINUTES)
@EnabledFor({ POSTGRESQL, DB2 })
// This should work for ORACLE but failing with
// Caused by: java.sql.SQLException: Not using JDBC
// at org.hibernate.reactive.provider.service.NoJdbcConnectionProvider.getConnection(NoJdbcConnectionProvider.java:25)
public class StructOnClassTest extends BaseReactiveTest {

private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() );

static Book book = createBook();
static Publisher ePublisher;
static Publisher pPublisher;

@Override
protected Collection<Class<?>> annotatedEntities() {
return List.of( Book.class );
}

private static Book createBook() {
ePublisher = new Publisher();
ePublisher.setName( "ebooks" );
ePublisher.setPubId( 5 );

pPublisher = new Publisher();
pPublisher.setName( "paperbooks" );
pPublisher.setPubId( 25 );

Book book = new Book();
book.title = "Hibernate";
book.author = "Steve";
book.ebookPublisher = ePublisher;
book.paperBackPublisher = pPublisher;
return book;
}

@BeforeEach
public void populateDB(VertxTestContext context) {
test( context, getSessionFactory()
.withTransaction( session -> session.persist( book )
.thenCompose( v -> session.flush() ) )
);
}

@Test
public void testStructComponent(VertxTestContext context) {
test( context, openSession()
.thenCompose( s2 -> s2.find( Book.class, book.id ) )
.thenAccept( resultBook -> {
assertNotNull( resultBook );
assertEquals( book.title, resultBook.title );
assertEquals( book.ebookPublisher.pubId, resultBook.ebookPublisher.pubId );
assertEquals( book.paperBackPublisher.pubId, resultBook.paperBackPublisher.pubId );
} )
);
}

@Entity(name = "Book")
public static class Book {

@Id
@GeneratedValue
private Long id;

private String title;

private String author;

@Column(name = "ebook_publisher")
private Publisher ebookPublisher;
private Publisher paperBackPublisher;
}

@Embeddable
@Struct( name = "publisher_type")
public static class Publisher {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

private Integer pubId;

public Integer getPubId() {
return pubId;
}

public void setPubId(Integer pubId) {
this.pubId = pubId;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.reactive;

import java.awt.Point;
import java.util.Collection;
import java.util.List;

import org.hibernate.annotations.Struct;
import org.hibernate.reactive.annotations.EnabledFor;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.vertx.junit5.Timeout;
import io.vertx.junit5.VertxTestContext;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

import static java.util.concurrent.TimeUnit.MINUTES;
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2;
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.POSTGRESQL;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@Timeout(value = 10, timeUnit = MINUTES)
@EnabledFor({ POSTGRESQL, DB2 })
// This should work for ORACLE but failing with
// Caused by: java.sql.SQLException: Not using JDBC
// at org.hibernate.reactive.provider.service.NoJdbcConnectionProvider.getConnection(NoJdbcConnectionProvider.java:25)
public class StructOnElementTest extends BaseReactiveTest {
static RecordStructHolder holder1;
static RecordStructHolder holder2;

@Override
protected Collection<Class<?>> annotatedEntities() {
return List.of( RecordStructHolder.class );
}

@BeforeEach
public void populateDB(VertxTestContext context) {
holder1 = new RecordStructHolder( 1L, new NamedPoint( "first", 1, 1 ) );
holder2 = new RecordStructHolder( 2L, new NamedPoint( "second", 2, 2 ) );
holder1.simpleStringHolder = new SimpleStringHolder( "column a","column b","column c" );

test( context, getSessionFactory()
.withTransaction( session -> session.persist( holder1, holder2 )
.thenCompose( v -> session.flush() ) )
);
}

@Test
public void testFindAndUpdate(VertxTestContext context) {
test( context, openSession()
.thenCompose( s2 -> s2.find( RecordStructHolder.class, holder1.id )
.thenAccept( resultHolder -> {
assertNotNull( resultHolder );
assertEquals( holder1.getThePoint().getPoint(), resultHolder.getThePoint().getPoint() );
resultHolder.setThePoint( new NamedPoint( "third", 3, 3 ) );
assertEquals( "third", resultHolder.getThePoint().name );
} )
.thenCompose( vv -> s2.flush() )
.thenCompose( vv -> s2.find( RecordStructHolder.class, holder1.id )
.thenAccept( found -> assertEquals( "third", found.getThePoint().getName() ) ) )
)
);
}

@Test
public void testSelectionItems(VertxTestContext context) {
test( context, openSession()
.thenCompose( s -> s.createSelectionQuery( "from RecordStructHolder where id = ?1", RecordStructHolder.class )
.setParameter( 1, holder1.getId() )
.getResultList() )
.thenAccept( holders -> {
assertNotNull( holders );
final RecordStructHolder holder = holders.get( 0 );
assertEquals( holder1.getThePoint().getPoint(), holder.getThePoint().getPoint() );
} )
);
}

@Test
public void testEmbeddedColumnOrder(VertxTestContext context) {
test( context, openSession()
.thenCompose( s2 -> s2.find( RecordStructHolder.class, holder1.id )
.thenAccept( resultHolder -> {
assertNotNull( resultHolder );
assertEquals( holder1.getThePoint().getPoint(), resultHolder.getThePoint().getPoint() );
assertEquals( "column a", holder1.simpleStringHolder.aColumn );
assertEquals( "column b", holder1.simpleStringHolder.bColumn );
assertEquals( "column c", holder1.simpleStringHolder.cColumn );
} )
)
);
}

@Entity(name = "RecordStructHolder")
public static class RecordStructHolder {
@Id
private Long id;
@Struct(name = "my_point_type")
private NamedPoint thePoint;

private SimpleStringHolder simpleStringHolder;

public RecordStructHolder() {
}

public RecordStructHolder(Long id, NamedPoint thePoint) {
this.id = id;
this.thePoint = thePoint;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public NamedPoint getThePoint() {
return thePoint;
}

public void setThePoint(NamedPoint point) {
this.thePoint = point;
}
}

@Embeddable
static class NamedPoint {
public String name;
public Point point;

public NamedPoint() {
}

public NamedPoint(String name, Integer x, Integer y) {
this.point = new Point( x, y );
this.name = name;
}

public String getName() {
return name;
}

public Point getPoint() {
return point;
}
}

// By default, the order of columns is based on the alphabetical ordering of the embeddable type attribute names.
// This class has column names re-defined using @Column annotation "name" attribute and will reverse the column order
@Embeddable
@Struct(name = "simple_string_holder")
static class SimpleStringHolder {
@Column(name = "c")
public String aColumn;
@Column(name = "b")
public String bColumn;
@Column(name = "a")
public String cColumn;

public SimpleStringHolder() {}

public SimpleStringHolder(String aColumn, String bColumn, String cColumn) {
this.aColumn = aColumn;
this.bColumn = bColumn;
this.cColumn = cColumn;
}
}
}

0 comments on commit 9cf65f3

Please sign in to comment.