hibernate 使用javax.sql.DataSource示例进行休眠

kb5ga3dv  于 2023-10-23  发布在  Java
关注(0)|答案(4)|浏览(145)

可以配置Hibernate来使用javax.sql.DataSource示例吗?
我的应用程序已经有了一个javax.sql.DataSource的示例,我不想仅仅为了休眠而重新配置数据库URL、用户、密码、驱动程序等。

n53p2ov0

n53p2ov01#

如果数据源可以通过JNDI获得,那么您只需要设置配置的hibernate.connection. configuration属性- mtpettyp的答案说明了这一点。
如果您所处的环境中的数据源不是来自JNDI,请提供您自己的ConnectionProvider实现,并在构建会话工厂之前将其传递给Settings对象,或者在hibernate.connection.provider_class属性中指定其类名。如果您为Settings提供了一个示例,那么您可能可以示例化标准DatasourceConnectionProvider并给予您的DataSource。

frebpwbc

frebpwbc2#

在您的hibernate.cfg.xml中:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>    
        <property name="connection.datasource">SampleDS</property>        
    </session-factory>

</hibernate-configuration>
xurqigkl

xurqigkl3#

如果您使用Spring初始化和Spring会话工厂Bean,则可以像这样简单地传入数据源

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    ...
</bean>

其中dataSource引用在别处定义。

4uqofj5v

4uqofj5v4#

    • 我是Hibernate和Jakarta Persistence的新手。我将来自不同来源的各种代码拼凑在一起,并进行了修改,直到它工作。

我找不到一个完整的例子来说明如何使用现有的DataSource示例仅通过代码(没有XML文件,没有JNDI)配置Hibernate/Jakarta Persistence。所以我把这个贴在这里。希望它能帮助其他人。
下面是一个使用Java SE的示例,没有任何Jakarta EE应用服务器。
我用的是:

  • 服务器:MySQL 8.1.0 on Linux in Docker Desktop 4.22.0 app for Apple Silicon(aarch 64)
  • 客户端:Hibernate Core 6.2.7.Final,它带来了Jakarta Persistence 3.1.0,带有JDBC驱动程序MySQL Connector/J 8.1.0,在IntelliJ IDEA 2023.2.1预览版中,在Java 20.0.2中,在MacBook Pro上的macOS Ventura上使用Apple M1 Pro芯片。

👉🏼 我用下面的代码严格配置了Hibernate。我没有写任何配置XML文件。

DataSource代码

javax.sql.DataSource与Java SE捆绑在一起。我们需要一个接口的实现。在本例中,我们使用com.mysql.cj.jdbc.MysqlDataSource类中JDBC驱动程序 MySQL Connector/J 提供的实现。
我们在下面的方法中设置了DataSource实现的一个示例。

private DataSource configureDataSource ( )
{
    com.mysql.cj.jdbc.MysqlDataSource dataSource = new com.mysql.cj.jdbc.MysqlDataSource ( );
    dataSource.setDatabaseName ( "bogus_" );
    dataSource.setServerName ( "localhost" );
    dataSource.setPort ( 8090 );
    dataSource.setUser ( "root" );
    dataSource.setPassword ( "" );  // WARNING: Risky business, leaving your server unprotected, without security. 
    return dataSource;
}

有关详细信息,请参阅 Connector/J 手册的Configuration Properties

休眠代码

有了这个DataSource示例,我们可以使用Hibernate连接到数据库服务器,执行查询,并将检索到的数据打包为对象。

Configuration cfg = new Configuration ( );
cfg.getProperties ( ).put ( Environment.DATASOURCE , this.dataSource );
cfg.addAnnotatedClass ( Book.class );
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder ( ).applySettings ( cfg.getProperties ( ) ).build ( );

try ( SessionFactory sessionFactory = cfg.buildSessionFactory ( serviceRegistry ) )
{
    Session session = sessionFactory.openSession ( );
    Query jpqlQuery = session.createQuery ( "SELECT b FROM Book b WHERE b.title=:title" , Book.class );
    jpqlQuery.setParameter ( "title" , "Our First Book" );
    Book book = ( Book ) jpqlQuery.getSingleResult ( );
    System.out.println ( "Retrieved via Hibernate… book = " + book );
}

Book = Book{id=1,title ='我们的第一本书',createdOn=2023-08- 14 T20:26:20.708102Z}

完整示例代码

Book类我们期望Hibernate示例化这个类的对象。

package work.basil.example.hibernate;

import jakarta.persistence.* ;

import java.time.OffsetDateTime;

@Entity
@Table(name = "book")
public class Book {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String title;

    @Column(name = "created_on")
    private OffsetDateTime createdOn;

    // Accessors

    public Long getId ( )
    {
        return id;
    }

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

    public String getTitle ( )
    {
        return title;
    }

    public void setTitle ( String title )
    {
        this.title = title;
    }

    public OffsetDateTime getCreatedOn ( )
    {
        return createdOn;
    }

    public void setCreatedOn ( OffsetDateTime createdOn )
    {
        this.createdOn = createdOn;
    }

    // Object overrides

    @Override
    public String toString ( )
    {
        return "Book{" +
               "id=" + id +
               ", title='" + title + '\'' +
               ", createdOn=" + createdOn +
               '}';
    }
}

以及我们完整的示例应用程序代码。代码:
1.重新创建一个表book。然后用单行重新填充该表。这两个步骤都直接使用JDBC,而不是Hibernate。
1.使用Hibernate查询单行,并使用检索到的数据示例化Book对象。

package work.basil.example.hibernate;

import jakarta.persistence.*;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;

import javax.sql.DataSource;
import java.sql.*;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.*;
import java.time.ZonedDateTime;

public class App
{
    final DataSource dataSource;

    private void demo ( )
    {
        this.dropTable ( );
        this.createTable ( );
        this.insertRow ( );
        this.dumpRows ( );
        this.dumpHibernate ( );
    }

    private void dumpHibernate ( )
    {
        Configuration cfg = new Configuration ( );
        cfg.getProperties ( ).put ( Environment.DATASOURCE , this.dataSource );
        cfg.addAnnotatedClass ( Book.class );
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder ( ).applySettings ( cfg.getProperties ( ) ).build ( );

        try ( SessionFactory sessionFactory = cfg.buildSessionFactory ( serviceRegistry ) )
        {
            Session session = sessionFactory.openSession ( );
            Query jpqlQuery = session.createQuery ( "SELECT b FROM Book b WHERE b.title=:title" , Book.class );
            jpqlQuery.setParameter ( "title" , "Our First Book" );
            Book book = ( Book ) jpqlQuery.getSingleResult ( );
            System.out.println ( "Retrieved via Hibernate… book = " + book );
        }
    }

    private void dumpRows ( )
    {
        String sql = """
                SELECT *
                FROM book
                 ;
                 """;
        try (
                Connection connection = this.dataSource.getConnection ( ) ;
                Statement statement = connection.createStatement ( ) ;
                ResultSet resultSet = statement.executeQuery ( sql ) ;
        )
        {
            record BookRecord( Long id , String title , OffsetDateTime odt ) { }
            while ( resultSet.next ( ) )
            {
                Long id = resultSet.getLong ( "id" );
                String title = resultSet.getString ( "title" );
                OffsetDateTime odt = resultSet.getObject ( "created_on" , OffsetDateTime.class );
                System.out.println ( new BookRecord ( id , title , odt ).toString ( ) );
            }
        }
        catch ( SQLException e )
        {
            throw new RuntimeException ( e );
        }
    }

    private void insertRow ( )
    {
        String sql = """
                INSERT INTO book
                ( title , created_on )
                VALUES
                ( ? , ? )
                 ;
                 """;
        try (
                Connection connection = this.dataSource.getConnection ( ) ;
                PreparedStatement preparedStatement = connection.prepareStatement ( sql ) ;
        )
        {
            ZonedDateTime zdt = ZonedDateTime.now ( ZoneId.of ( "America/Edmonton" ) ); // Capture the current moment as seen in a particular time zone.
            OffsetDateTime odt = zdt.toOffsetDateTime ( );  // Discard the time zone, keeping only a mere offset-from-UTC. Not an improvement, but standard SQL does not support only offsets, not time zones.
            Instant instant = odt.toInstant ( );  // Adjust to an offset from UTC of zero hours-minutes-seeconds.
            System.out.println ( "zdt = " + zdt );  // Be aware: All three of these date-time objects represent the very same moment, the same point on the timeline.
            System.out.println ( "odt = " + odt );
            System.out.println ( "instant = " + instant );
            preparedStatement.setString ( 1 , "Our First Book" );
            preparedStatement.setString ( 2 , odt.toString ( ) );
            preparedStatement.executeUpdate ( );
        }
        catch ( SQLException e )
        {
            throw new RuntimeException ( e );
        }
    }

    private void dropTable ( )
    {
        String sql = """
                DROP TABLE IF EXISTS book
                ;
                """;
        try (
                Connection connection = this.dataSource.getConnection ( ) ;
                Statement statement = connection.createStatement ( ) ;
        )
        {
            statement.executeUpdate ( sql );
        }
        catch ( SQLException e )
        {
            throw new RuntimeException ( e );
        }
    }

    private void createTable ( )
    {
        String sql = """
                CREATE TABLE book (
                    id BIGINT AUTO_INCREMENT PRIMARY KEY ,
                    title VARCHAR(255) NOT NULL ,
                    created_on TIMESTAMP(6) NOT NULL
                ) ;
                """;
        try (
                Connection connection = this.dataSource.getConnection ( ) ;
                Statement statement = connection.createStatement ( ) ;
        )
        {
            statement.executeUpdate ( sql );
        }
        catch ( SQLException e )
        {
            throw new RuntimeException ( e );
        }
    }

    // Constructor
    public App ( )
    {
        this.dataSource = this.configureDataSource ( );
    }

    private DataSource configureDataSource ( )
    {
        com.mysql.cj.jdbc.MysqlDataSource dataSource = new com.mysql.cj.jdbc.MysqlDataSource ( );
        dataSource.setDatabaseName ( "bogus_" );
        dataSource.setServerName ( "localhost" );
        dataSource.setPort ( 8090 );
        dataSource.setUser ( "root" );
        dataSource.setPassword ( "" );  // WARNING: Risky business, leaving your server unprotected, without security.
        return dataSource;
    }

    public static void main ( String[] args )
    {
        App app = new App ( );
        app.demo ( );
    }

    private void dumpTime ( )
    {
        String sql = "SELECT CURRENT_TIMESTAMP  ;";
        try (
                Connection connection = this.dataSource.getConnection ( ) ;
                Statement statement = connection.createStatement ( ) ;
                ResultSet resultSet = statement.executeQuery ( sql ) ;
        )
        {
            while ( resultSet.next ( ) )
            {
                String now = resultSet.getString ( 1 );
                System.out.println ( now + "\n" );
            }
        }
        catch ( SQLException e )
        {
            throw new RuntimeException ( e );
        }
    }
}

运行时:

zdt = 2023-08-14T14:26:20.708102-06:00[America/Edmonton]
odt = 2023-08-14T14:26:20.708102-06:00
instant = 2023-08-14T20:26:20.708102Z
BookRecord[id=1, title=Our First Book, odt=2023-08-14T20:26:20.708102-07:00]
Aug 14, 2023 1:26:20 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.2.7.Final
Aug 14, 2023 1:26:20 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000406: Using bytecode reflection optimizer
Aug 14, 2023 1:26:21 PM org.hibernate.bytecode.internal.BytecodeProviderInitiator buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : bytebuddy
Aug 14, 2023 1:26:21 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Retrieved via Hibernate… book = Book{id=1, title='Our First Book', createdOn=2023-08-14T20:26:20.708102Z}

相关问题