1 // $Id: DialectFactory.java 9789 2006-04-25 17:06:55Z epbernard $
2 package org.hibernate.dialect;
3
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.Properties;
7
8 import org.hibernate.HibernateException;
9 import org.hibernate.cfg.Environment;
10 import org.hibernate.util.ReflectHelper;
11
12 /**
13 * A factory for generating Dialect instances.
14 *
15 * @author Steve Ebersole
16 */
17 public class DialectFactory {
18
19 /**
20 * Builds an appropriate Dialect instance.
21 * <p/>
22 * If a dialect is explicitly named in the incoming properties, it is used. Otherwise, the database name and version
23 * (obtained from connection metadata) are used to make the dertemination.
24 * <p/>
25 * An exception is thrown if a dialect was not explicitly set and the database name is not known.
26 *
27 * @param props The configuration properties.
28 * @param databaseName The name of the database product (obtained from metadata).
29 * @param databaseMajorVersion The major version of the database product (obtained from metadata).
30 *
31 * @return The appropriate dialect.
32 *
33 * @throws HibernateException No dialect specified and database name not known.
34 */
35 public static Dialect buildDialect(Properties props, String databaseName, int databaseMajorVersion)
36 throws HibernateException {
37 String dialectName = props.getProperty( Environment.DIALECT );
38 if ( dialectName == null ) {
39 return determineDialect( databaseName, databaseMajorVersion );
40 }
41 else {
42 return buildDialect( dialectName );
43 }
44 }
45
46 /**
47 * Determine the appropriate Dialect to use given the database product name
48 * and major version.
49 *
50 * @param databaseName The name of the database product (obtained from metadata).
51 * @param databaseMajorVersion The major version of the database product (obtained from metadata).
52 *
53 * @return An appropriate dialect instance.
54 */
55 public static Dialect determineDialect(String databaseName, int databaseMajorVersion) {
56 if ( databaseName == null ) {
57 throw new HibernateException( "Hibernate Dialect must be explicitly set" );
58 }
59
60 DatabaseDialectMapper mapper = ( DatabaseDialectMapper ) MAPPERS.get( databaseName );
61 if ( mapper == null ) {
62 throw new HibernateException( "Hibernate Dialect must be explicitly set for database: " + databaseName );
63 }
64
65 String dialectName = mapper.getDialectClass( databaseMajorVersion );
66 return buildDialect( dialectName );
67 }
68
69 /**
70 * Returns a dialect instance given the name of the class to use.
71 *
72 * @param dialectName The name of the dialect class.
73 *
74 * @return The dialect instance.
75 */
76 public static Dialect buildDialect(String dialectName) {
77 try {
78 return ( Dialect ) ReflectHelper.classForName( dialectName ).newInstance();
79 }
80 catch ( ClassNotFoundException cnfe ) {
81 throw new HibernateException( "Dialect class not found: " + dialectName );
82 }
83 catch ( Exception e ) {
84 throw new HibernateException( "Could not instantiate dialect class", e );
85 }
86 }
87
88 /**
89 * For a given database product name, instances of
90 * DatabaseDialectMapper know which Dialect to use for different versions.
91 */
92 public static interface DatabaseDialectMapper {
93 public String getDialectClass(int majorVersion);
94 }
95
96 /**
97 * A simple DatabaseDialectMapper for dialects which are independent
98 * of the underlying database product version.
99 */
100 public static class VersionInsensitiveMapper implements DatabaseDialectMapper {
101 private String dialectClassName;
102
103 public VersionInsensitiveMapper(String dialectClassName) {
104 this.dialectClassName = dialectClassName;
105 }
106
107 public String getDialectClass(int majorVersion) {
108 return dialectClassName;
109 }
110 }
111
112 private static final Map MAPPERS = new HashMap();
113 static {
114 // TODO : this is the stuff it'd be nice to move to a properties file or some other easily user-editable place
115 MAPPERS.put( "HSQL Database Engine", new VersionInsensitiveMapper( "org.hibernate.dialect.HSQLDialect" ) );
116 MAPPERS.put( "DB2/NT", new VersionInsensitiveMapper( "org.hibernate.dialect.DB2Dialect" ) );
117 MAPPERS.put( "MySQL", new VersionInsensitiveMapper( "org.hibernate.dialect.MySQLDialect" ) );
118 MAPPERS.put( "PostgreSQL", new VersionInsensitiveMapper( "org.hibernate.dialect.PostgreSQLDialect" ) );
119 MAPPERS.put( "Microsoft SQL Server Database", new VersionInsensitiveMapper( "org.hibernate.dialect.SQLServerDialect" ) );
120 MAPPERS.put( "Microsoft SQL Server", new VersionInsensitiveMapper( "org.hibernate.dialect.SQLServerDialect" ) );
121 MAPPERS.put( "Sybase SQL Server", new VersionInsensitiveMapper( "org.hibernate.dialect.SybaseDialect" ) );
122 MAPPERS.put( "Informix Dynamic Server", new VersionInsensitiveMapper( "org.hibernate.dialect.InformixDialect" ) );
123 MAPPERS.put( "Apache Derby", new VersionInsensitiveMapper( "org.hibernate.dialect.DerbyDialect" ) );
124
125 MAPPERS.put(
126 "Oracle",
127 new DatabaseDialectMapper() {
128 public String getDialectClass(int majorVersion) {
129 return majorVersion > 8
130 ? "org.hibernate.dialect.Oracle9Dialect"
131 : "org.hibernate.dialect.OracleDialect";
132 }
133 }
134 );
135 }
136 }